题意:4×4的棋盘上有一些黑白棋,要求翻多少个子能翻成全黑或者全白
思路:dfs,翻哪个棋子顺序不影响,所以最多2的16次方种可能
用状态压缩来表示每个位置,第0位表示(0,0),第1位表示(0,1),以此类推
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char field[5][5];
const int dir[4][2]={-1,0,0,1,1,0,0,-1};
const int allblack=(1<<16)-1;
int trans(int i,int j)
{
return i*4+j;
}
void untrans(int p,int &i,int &j)
{
i=p/4;
j=p%4;
}
inline bool judge(int x,int y)
{
if(x>=4||x<0)return false;
if(y>=4||y<0)return false;
return true;
}
int ans;
void dfs(const int sta,int step,int x,int y)
{
if(sta==0||sta==allblack){
if(ans==-1||ans>step)ans=step;
return ;
}
if(x>=4||y>=4)return;
int change=sta;
int tmp=trans(x,y);
change^=(int)(1<<tmp);
for(int i=0;i<4;++i){
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if(!judge(tx,ty))continue;
int pos=trans(tx,ty);
change^=(int)(1<<pos);
}
int tx=x;
int ty=y;
ty++;
untrans(trans(tx,ty),tx,ty);
dfs(sta,step,tx,ty);
dfs(change,step+1,tx,ty);
}
int main()
{
// freopen("data.txt","r",stdin);
int start=0;
ans=-1;
for(int i=0;i<4;++i)
{
scanf("%s",field[i]);
for(int j=0;j<4;++j){
if(field[i][j]=='b'){
int z=trans(i,j);
start|=(1<<z);
}
}
}
dfs(start,0,0,0);
if(ans==-1)puts("Impossible");
else printf("%d\n",ans);
return 0;
}