POJ_1681,画家问题,同熄灯问题(POJ_2811),通过二进制枚举第一行的情况后逐行操作,判断最后一行是否全涂色
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
bool floors[20][20],copyf[20][20];
int main(){
int test;
for(cin>>test;test>0;test--){
int length,allop,count; cin>>length;
bool hasans=0;
for(int i=1;i<=length;i++) //地板编号从1到length
for(int j=1;j<=length;j++){
char c; cin>>c;
if(c=='y') floors[i][j]=1;
else floors[i][j]=0;
}
if(length==1){
if(floors[1][1]){
cout<<0<<endl;
continue;
}
else{
cout<<1<<endl;
continue;
}
}
for(allop=0;allop<pow(2,length);allop++){ //第一行操作编号从0到2^length-1
int copya=allop;
count=0;
for(int i=1;i<=length;i++)
for(int j=1;j<=length;j++)
copyf[i][j]=floors[i][j];
bool op[length+1];
memset(op,0,sizeof(op));
for(int i=1;copya!=0;i++){ //将第一行操作按二进制表示,位号从1到length
if(copya%2) op[i]=1;
copya/=2;
}
for(int i=1;i<=length;i++){ //第一行根据二进制进行操作
if(op[i]){
count++;
copyf[1][i]=copyf[1][i]^1; //取反:与1异或
copyf[2][i]=copyf[2][i]^1;
copyf[1][i-1]=copyf[1][i-1]^1;
copyf[1][i+1]=copyf[1][i+1]^1;
}
}
for(int i=2;i<=length;i++) //第二到length行根据上一行进行操作
for(int j=1;j<=length;j++)
if(!copyf[i-1][j]){
count++;
copyf[i][j]=copyf[i][j]^1;
copyf[i+1][j]=copyf[i+1][j]^1;
copyf[i][j-1]=copyf[i][j-1]^1;
copyf[i][j+1]=copyf[i][j+1]^1;
}
bool flag=1;
for(int i=1;i<=length;i++) //第length行检查
if(!copyf[length][i]){
flag=0;
break;
}
if(flag){
hasans=1;
break;
}
}
if(hasans) cout<<count<<endl;
else cout<<"inf"<<endl;
}
return 0;
}