POJ 1753
要求:4*4的黑白棋盘,w代表白色棋子,b代表黑色棋子,每次改变一个棋子的颜色,它周围紧邻的所有棋子均变色。
方法:递归暴搜。
1.预处理白色为0,黑色为1。
2.每个棋子只能翻0次或1次,每翻两次和不翻一样,翻0个棋子,翻1个棋子,...,翻16个棋子,共2^16次方种方案。
3.因数据过小,可直接递归暴搜,用生成16位二进制数的方法决定取棋子的策略。
4.每种方案进行判定,若和为0或65535(全0和全1),则符合要求。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[20],num[20],temp[20],ans=17;
int two[16]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,
8192,16384,32768};
void judge()
{
int i,j,cnt=0,sum=0;
memcpy(temp,num,sizeof(num));
for(i=0;i<16;i++)
{
if(a[i])
{
cnt++;
temp[i]=1-temp[i];
if(i-4>=0) temp[i-4]=1-temp[i-4];
if(i+4<16) temp[i+4]=1-temp[i+4];
if(i%4!=0) temp[i-1]=1-temp[i-1];
if(i%4!=3) temp[i+1]=1-temp[i+1];
}
}
for(i=0;i<16;i++)
{
if(temp[i])
{
sum+=two[i];
}
}
if(sum==0||sum==65535) ans=min(ans,cnt);
}
void dfs(int n)
{
int i;
if(n==16)
{
judge();
return;
}
for(i=0;i<2;i++)
{
a[n]=i;
dfs(n+1);
}
}
int main()
{
int i,j,t;
char s[20];
for(i=0;i<4;i++)
{
scanf("%s",&s);
for(j=0;j<4;j++)
{
if(s[j]=='b') num[i*4+j]=1;
else num[i*4+j]=0;
}
}
dfs(0);
if(ans<=16) printf("%d\n",ans);
else printf("Impossible\n");
}