原题地址:http://bailian.openjudge.cn/practice/2813/
思路完全和熄灯问题一致,代码如下:
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
//解题思路跟熄灯问题完全一样,代码参照郭炜老师熄灯问题代码,枚举第一行的状态,则后面所有行状态都已经确定;
//用16位的short型存储每个方块的状态,1表示白色,0表示黄色。
void setbit(short&a,int i,int v){ //初始化墙块状态函数
if(v) a|=(1<<i);
else a&=~(1<<i);
}
int getbit(short a,int i){ //获取某位二进制数的值
return (a>>i)&1;
}
void flip(short&a,int i){ //翻转某位二进制的值
a^=(1<<i);
}
int count(short a){ //判断二进制数里面1的个数,用来统计需要操作的步数;
int num=0;
while(a!=0){
a=a&a-1;
num++;
}
return num;
}
int main()
{
char s[16][16];
int n;
int min=1<<30;
short op; //op用来表示当前行的操作情况,1表示需要涂黄;
cin>>n;
short *ori=new short[n]; //ori用来存储原始墙块状态
short *m=new short[n]; //m用来存储处理过程中的墙块状态
memset(ori,0,2*n);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>s[i][j];
if(s[i][j]=='w') setbit(ori[i],j,1);
else setbit(ori[i],j,0);
}
getchar();
}
for(int i=0;i<pow(2,n);i++){
memcpy(m,ori,2*n);
op=i;
int num=count(op);
for(int j=0;j<n;j++){
if(num>=min) break;
for(int k=0;k<n;k++){
if(getbit(op,k)){
if(k>0) flip(m[j],k-1);
flip(m[j],k);
if(k<n-1) flip(m[j],k+1);
}
}//k
if(j<n-1) m[j+1]^=op; //下一行墙的状态和当前行操作情况异或之后就是下一行的状态;
op=m[j]; //下一行需要操作的和当前行状态一样
num+=count(op);
}//j
if(m[n-1]==0){ //最后一行为0表示全部变黄
if(num<min) min=num;
// cout<<min<<endl;
}
}//i
if(min!=(1<<30)) cout<<min<<endl;
else cout<<"inf"<<endl;
delete []m;
delete []ori;
return 0;
}