【贪心】Google Code Jam Round 1A 2018 Waffle Choppers

题意:给你一个矩阵,有些点是黑的,让你横切h刀,纵切v刀,问你是否能让切出的全部子矩阵的黑点数量相等。数组

设黑点总数为sum,sum必须能整除(h+1),进而sum/(h+1)必须能整除(v+1)。spa

先考虑横行,贪心地扫过去,若是到了某一行,当前统计的黑点数刚好为sum/(h+1),就在这里切一刀,接着统计。不然,若是>sum/(h+1),则无解。在这个过程当中,每一行被切到哪一横组里就肯定了。blog

而后纵切,过程跟横切相似,只不过统计的不是一个变量,而是一个大小为(h+1)的数组,若是到了某一列,当前统计的数组的每一个份量的黑点数刚好为sum/(h+1)/(v+1),就在这里切一刀,接着统计。不然,若是数组的某个份量>sum/(h+1),则无解。string

#include<cstdio>
#include<cstring>
using namespace std;
int T,n,m,h,v;
char a[105][105];
int hq[105];
int cnts[105],t;
bool check1(){
	for(int i=1;i<=h+1;++i){
		if(cnts[i]!=t){
			return 0;
		}
	}
	return 1;
}
bool check2(){
	for(int i=1;i<=h+1;++i){
		if(cnts[i]>t){
			return 0;
		}
	}
	return 1;
}
int main(){
	//freopen("a.in","r",stdin);
	scanf("%d",&T);
	for(int zu=1;zu<=T;++zu){
		printf("Case #%d: ",zu);
		scanf("%d%d%d%d",&n,&m,&h,&v);
		for(int i=1;i<=n;++i){
			scanf("%s",a[i]+1);
		}
		int sum=0;
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				sum+=(a[i][j]=='@');
			}
		}
		if(sum%(h+1)!=0){
			puts("IMPOSSIBLE");
			continue;
		}
		t=sum/(h+1);
		int cnt=0;
		bool flag=1;
		int last=0,num=0;
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				cnt+=(a[i][j]=='@');
			}
			if(cnt==t){
				++num;
				for(int k=last+1;k<=i;++k){
					hq[k]=num;
				}
				last=i;
				cnt=0;
			}
			else if(cnt>t){
				flag=0;
				break;
			}
		}
		if(!flag){
			puts("IMPOSSIBLE");
			continue;
		}
		
		if(sum/(h+1)%(v+1)!=0){
			puts("IMPOSSIBLE");
			continue;
		}
		t=sum/(h+1)/(v+1);
		memset(cnts,0,sizeof(int)*(2+h));
		flag=1;
		for(int i=1;i<=m;++i){
			for(int j=1;j<=n;++j){
				cnts[hq[j]]+=(a[j][i]=='@');
			}
			if(check1()){
				memset(cnts,0,sizeof(int)*(2+h));
			}
			else if(!check2()){
				flag=0;
				break;
			}
		}
		if(!flag){
			puts("IMPOSSIBLE");
			continue;
		}
		puts("POSSIBLE");
	}
	return 0;
}
相关文章
相关标签/搜索