分析:1、每格棋子最多只可以翻转一次(实际是奇数次,但这没意义),只要其中一格重复翻了2次(不论是连续翻动还是不连翻动),那么它以及周边的棋子和没翻动时的状态是 一致的,由此就可以确定这个棋盘最多只能走16步,最多只能有翻出2^16种状态
2、翻与不翻,分别向下搜索。就像那个在一列数中找和为m的排列,每次数都有取与不取两种可能,取并向下搜索,不取向下搜索,如果找到就返回或输出。类比可知。翻与不翻,翻,deep+1,因为翻这算一步。如果不翻,这一步就不能加。
3、在0—16范围内不断的加大搜索的步数,一旦达到步数就停止搜索开始检查,以便更快的搜索到最优解。(迭代加深dfs的思想)
代码:
#include<cstdio>
#include<iostream>
using namespace std;
bool m[6][6]={false};
char maps[6][6];
int step;
bool flag;
int dx[5]={-1,1,0,0,0};
int dy[5]={0,0,-1,1,0};
void flip(int r,int c)
{
for(int i=0;i<5;i++)
m[r+dx[i]][c+dy[i]]=!m[r+dx[i]][c+dy[i]];
}
bool check()
{
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
if(m[i][j]!=m[1][1])
return false;
}
}
return true;
}
void dfs(int row,int col,int deep)
{
if(deep==step)
{
flag=check();
return;
}
if(flag||row==5)
return;
flip(row,col);
if(col<4)
dfs(row,col+1,deep+1);
else
dfs(row+1,1,deep+1);
flip(row,col);
if(col<4)
dfs(row,col+1,deep);
else
dfs(row+1,1,deep);
return;
}
int main()
{
for(int i=1;i<=4;i++)
{
scanf("%s",maps[i]+1);
for(int j=1;j<=4;j++)
{
if(maps[i][j]=='b')
m[i][j]=true;
}
}
for(step=0;step<=16;step++)
{
dfs(1,1,0);
if(flag) break;
}
if(flag) printf("%d\n",step);
else printf("Impossible\n");
return 0;
}
11915245 | Accepted | 144K | 313MS | 1257B | 2013-08-03 23:45:41 |