zoukankan      html  css  js  c++  java
  • HZOI20190903模拟36 字符,蛋糕,游戏

    题面:https://www.cnblogs.com/Juve/articles/11461528.html

    A:字符

    暴力模拟一下,细节很多,但是暴力思路都不大一样

    先枚举循环节长度,然后处理一个b数组,表示根据已知条件能推出的循环节,不能确定的位置是0

    比如第一个样例,在len=5时的b数组是01203,(颜色从1到c,位置从0到len-1)表示第0位和第3位不能确定

    在求b数组时顺便可以check这个循环节是否合法

    然后求一个pos数组,pos[i]表示i在b数组中最后出现的位置,如果这个颜色没有在b数组中出现,那么pos=-1

    然后就可以统计答案,根据贪心,sum[i]=pos[i]-pos[i-1],如果pos[i]=-1,那么sum[i]=1,pos[i]=pos[i-1]+1,

    这时check你的pos数组是否大于0,如果不是,则该循环节不合法

    比如:01040,其中sum[3]=0,不合法,需要判掉

    然后输出sum就可以了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define re register
    #define MAXM 100005
    using namespace std;
    int t,c,m,maxt,b[MAXM],sum[MAXM],pos[MAXM];
    bool flag=0;
    struct node{
    	int pk,xk;
    	friend bool operator < (node p,node q){
    		return p.pk<q.pk;
    	}
    }a[MAXM];
    bool judge(int len){
    	for(int i=0;i<=c;i++) pos[i]=-1;
    	memset(b,0,sizeof(b));
    	for(int i=1;i<=m;i++){
    		if(b[(a[i].pk-1)%len]==0){
    			b[(a[i].pk-1)%len]=a[i].xk+1;
    		}else{
    			if(b[(a[i].pk-1)%len]==a[i].xk+1) continue;
    			else return 0;
    		}
    	}
    	int maxx=0;
    	for(int i=0;i<len;i++){
    		maxx=max(maxx,b[i]);
    		if(b[i]) pos[b[i]]=i;
    		if(b[i]!=0&&b[i]<maxx) return 0;
    	}
    	return 1;
    }
    bool check(int len){
    	int p=0;
    	for(int i=1;i<=c;i++){
    		if(pos[i]==-1){
    			pos[i]=pos[i-1]+1;
    			sum[i]=1;
    		}else sum[i]=pos[i]-pos[i-1];
    		if(sum[i]<=0) return 0;
    		p+=sum[i];
    	}
    	p-=sum[c];
    	sum[c]=len-pos[c-1]-1;
    	if(sum[c]<=0) return 0;
    	p+=sum[c];
    	return p==len;
    }
    signed main(){
    	//freopen("test.in","r",stdin);
    	//freopen("vio.out","w",stdout);
    	scanf("%d%d",&t,&c);
    	while(t--){
    		scanf("%d",&m);
    		if(m==0){
    			for(int i=1;i<=c;i++) printf("1 ");
    			puts("");
    			continue;
    		}
    		for(int i=1;i<=m;i++)
    			scanf("%d%d",&a[i].pk,&a[i].xk);
    		sort(a+1,a+m+1);
    		maxt=a[m].pk+c;
    		for(int i=1;i<=m;i++){
    			if(a[i].xk<a[i-1].xk){
    				maxt=a[i].pk;
    				break;
    			}
    		}
    		memset(sum,0,sizeof(sum));
    		flag=0;
    		for(int i=c;i<=maxt;i++){
    			if(judge(i)){
    				//for(int j=0;j<i;j++){
    				//	cout<<b[j]<<' ';
    				//}
    				//cout<<endl;
    				if(check(i)){
    					flag=1;
    					for(int j=1;j<=c;j++) printf("%d ",sum[j]);
    					puts("");
    					break;
    				}
    			}
    		}
    		if(flag==0) puts("NO");
    	}
    	return 0;
    }
    

    B:蛋糕

    区间dp,记f[i][j]表示拿完环上的区间[i,j]的蛋糕大小之和的最大值,按区间长度的奇偶性转移

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 4005
    #define re register
    #define int long long
    using namespace std;
    int n,a[MAXN],ans=0,f[MAXN][MAXN];
    signed main(){
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&a[i]);
    		a[i+n]=a[i];
    		f[i][i]=f[n+i][n+i]=a[i];
    	}
    	a[0]=a[n];
    	for(int k=1;k<n;++k){
    		for(int l=1;l+k<=2*n;++l){
    			int r=l+k-1;
    			if(k&1){
    				if(a[l-1]>a[r+1]) f[l-1][r]=max(f[l-1][r],f[l][r]);
    				else f[l][r+1]=max(f[l][r+1],f[l][r]);
    			}else{
    				f[l-1][r]=max(f[l-1][r],f[l][r]+a[l-1]);
    				f[l][r+1]=max(f[l][r+1],f[l][r]+a[r+1]);
    			}
    		}
    	}
    	for(int i=1;i<=n;++i) ans=max(ans,f[i][i+n-1]);
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    C:游戏

    可以发现,整个过程一定是如下过程的重复:最近的莉露露过来,带上由岐,移动一段距离,然后把由岐抛出去,而且每个莉露露只会行动至多一
    次。但是如果暴力建出所有AL+B的边的话复杂度过高,考虑把它拆成B+A+···+A的形式,即每移动1的距离就增加A。可以对每个点(x,y)设置三个状态,记在南北方向被抛出的过程中为(x,y,0)、在东西方向被抛出的过程中为(x,y,1)、在被带着移动的过程中为(x,y,2)。(x,y,0)向(x±1,y,0)连边权为A的有向边,(x,y,1)向(x,y±1,1)连边权为A的有向边,表示正在抛出;(x,y,2)向(x,y,0/1)连边权为B的有向边,表示开始抛出;(x,y,0/1)向(x,y,2)连边权为d(x,y)的有向边(其中d(x,y)表示初始位置离(x,y)最近的莉露露的距离乘C,这可以通过多源点BFS预处理出来),表示落地后最近的莉露露移动过来;(x,y,2)向周围四个方向连边权为C的有向边,表示正在移动。这样建图后,(x1,y1,2)到(xn,yn,0/1/2)的最短路即为答案。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define MAXN 4000005
    #define MAXM 4000005
    #define int long long
    using namespace std;
    int x,y,a,b,c,n,tot,d[505][505],ans=0;
    int dx[4]={1,0,-1,0};
    int dy[4]={0,1,0,-1};
    struct node{
    	int x,y;
    }lilulu[MAXN];
    queue< pair<int,int> >que;
    int to[MAXM],nxt[MAXM],pre[MAXM],val[MAXM],cnt=0;
    void add(int u,int v,int w){
    	++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt,val[cnt]=w;
    }
    int id(int i,int j,int k){
    	return (i-1)*y+j+k*tot;
    }
    int dis[MAXN];
    priority_queue< pair<int, int> > q;
    bool visit[MAXN];
    void dijkstra(int x){
    	memset(dis,0x3f,sizeof(dis));
    	dis[x]=0;
    	memset(visit,0,sizeof(visit));
    	q.push(make_pair(-dis[x],x));
    	while(!q.empty()){
    		int y=q.top().second;q.pop();
    		if(visit[y]) continue;
    		visit[y]=1;
    		for(int i=pre[y];i;i=nxt[i]){
    			int v=to[i],z=val[i];
    			if(dis[v]>dis[y]+z){
    				dis[v]=dis[y]+z;
    				q.push(make_pair(-dis[v],v));
    			}
    		}
    	}
    }
    signed main(){
    	scanf("%lld%lld",&x,&y);
    	++x,++y;
    	tot=x*y;
    	memset(d,0x3f,sizeof(d));
    	scanf("%lld%lld%lld",&a,&b,&c);
    	scanf("%lld",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%lld%lld",&lilulu[i].x,&lilulu[i].y);
    		lilulu[i].x++,lilulu[i].y++;
    		que.push(make_pair(lilulu[i].x,lilulu[i].y));
    		d[lilulu[i].x][lilulu[i].y]=0;
    	}
    	while(!que.empty()){
    		pair<int,int>pa=que.front();
    		que.pop();
    		for(int i=0;i<4;i++){
    			int p=pa.first+dx[i],q=pa.second+dy[i];
    			if(p>0&&q>0&&p<=x&&q<=y){
    				if(d[p][q]>d[pa.first][pa.second]+1){
    					d[p][q]=d[pa.first][pa.second]+1;
    					que.push(make_pair(p,q));
    				}
    			}
    		}
    	}
    	for(int i=1;i<=x;i++){
    		for(int j=1;j<=y;j++){
    			if(i-1>0) add(id(i,j,0),id(i-1,j,0),a);
    			if(i+1<=x) add(id(i,j,0),id(i+1,j,0),a);
    			if(j-1>0) add(id(i,j,1),id(i,j-1,1),a);
    			if(j+1<=y) add(id(i,j,1),id(i,j+1,1),a);
    			add(id(i,j,2),id(i,j,0),b),add(id(i,j,2),id(i,j,1),b);
    			for(int k=0;k<4;k++){
    				int p=i+dx[k],q=j+dy[k];
    				if(p>0&&q>0&&p<=x&&q<=y) add(id(i,j,2),id(p,q,2),c);
    			}
    			add(id(i,j,0),id(i,j,2),c*d[i][j]),add(id(i,j,1),id(i,j,2),c*d[i][j]);
    		}
    	}
    	dijkstra(id(lilulu[1].x,lilulu[1].y,2));
    	ans=min(dis[id(lilulu[n].x,lilulu[n].y,2)],min(dis[id(lilulu[n].x,lilulu[n].y,1)],dis[id(lilulu[n].x,lilulu[n].y,0)]));
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    PHP htmlspecialchars和htmlspecialchars_decode(函数)
    使用CURL抓取淘宝页面
    PHP 自定义字符串中的变量名解析
    Notepad++前端开发常用插件介绍
    使用phpExcel实现Excel数据的导入导出(完全步骤)
    moment.js 日期包装类 (说明示例)
    php函数前面加&符号 和 变量前面加&符号的意义
    window 查看端口/杀进程
    eureka 去除注册中心保护机制
    mysql 表关联更新另一张表的数据
  • 原文地址:https://www.cnblogs.com/Juve/p/11468203.html
Copyright © 2011-2022 走看看