【貪心】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;
}
相關文章
相關標籤/搜索