本题要注意的就是深搜时的归位问题,以及枚举步数时的最大翻动次数,16是个思维点。
推荐两篇题解:http://www.cnblogs.com/shuaiwhu/archive/2012/04/27/2474041.html
http://blog.csdn.net/hackbuteer1/article/details/7392245
看到很多人用位运算+bfs解,也是一种很好的思路。
//Memory Time
//132K 344MS
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int chess[6][6];//中间4*4方阵有效
int r[5]={0,1,0,-1,0};//判断是否同色时使用
int c[5]={-1,0,1,0,0};
int step;
int flag;
int judge()//判断同色函数
{
for(int i=1;i<5;i++)
for(int j=1;j<5;j++)
if(chess[i][j]!=chess[1][1])
return 0;
return 1;
}
void reverse(int row,int col)//翻转棋子函数
{
for(int i=0;i<5;i++)
{
if(chess[row+r[i]][col+c[i]]==1)
chess[row+r[i]][col+c[i]]=0;
else
chess[row+r[i]][col+c[i]]=1;
}
}
int dfs(int row,int col,int deep)//深搜
{
if(deep==step)
{
return flag=judge();
}
if(flag||row>=5)
return 0;
reverse(row,col);
if(col<4)
dfs(row,col+1,deep+1);
else
dfs(row+1,1,deep+1);//如果列大于4了就要进入下一行从第一列开始继续搜索
reverse(row,col);//前面没找到解的话就要将棋子再翻回来
if(col<4)
dfs(row,col+1,deep);
else
dfs(row+1,1,deep);
}
int main()
{
char t;
for(int i=1;i<5;i++)
{
for(int j=1;j<5;j++)
{
scanf("%c",&t);
if(t=='b')
chess[i][j]=1;
else
chess[i][j]=0;
}
getchar();
}
for(step=0;step<=16;step++)//步数最大是16,因为一共16格,任意一格翻转两次相当于没动
{ //即翻动16次以上时必定有棋子又被翻转回去了
dfs(1,1,0);
if(flag)
{
printf("%d\n",step);
break;
}
}
if(!flag)
puts("Impossible\n");
return 0;
}