題意:給你一個矩陣,有些點是黑的,讓你橫切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; }