您的位置:首页 > 其它

poj1753 Flip Game 解题报告

2013-06-09 23:14 411 查看
现附上原题连接:http://poj.org/problem?id=1753

题目的大意识这样:

给一个棋盘,4*4大小,上面放上正反面各为黑、白的棋子,现有如下操作:

1、在其中选一棋子,完成反转操作,反转后,棋子颜色改变为其对立颜色。

2、凡是反转一枚棋子,其上下左右邻近位置的棋子均要翻面。

问:给定一种状态下的局面,需要翻至少几个棋子,会使棋盘全是白色或全是黑色。

输入:w:白色,b:黑色。

输出:1、反转个数。

2、impossible。

思路:可以枚举所有情况,反转的次数一定不会大于16次,因为棋盘的棋子个数就为16。可以证明,当超过16次时,会重复前面的情况。那么这样,我们可以通过深搜,来实现对所有情况的枚举。

策略:对所给状态,进行在1到16各次数下的深搜,如果得到终态(即黑或白的情况)就得出结果。注意初始态就为终态的情况,此时反转次数为0.

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
int mat[4][4];
int flag,step;
void init_graph(){
char c;
for(int i=0;i<4;i++){
if(i)getchar();
for(int j=0;j<4;j++){
scanf("%c",&c);
if(c=='b')mat[i][j]=0;
else if(c=='w')mat[i][j]=1;
}
}

}
void test()
{
for(int i=0;i<4;i++){
if(i)printf("\n");
for(int j=0;j<4;j++)
printf("%d",mat[i][j]);
}
}
int judge(){
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(mat[i][j]!=mat[0][0])return 0;
return 1;
}
void alter(int i,int j){
mat[i][j]=!mat[i][j];
if(i>0)mat[i-1][j]=!mat[i-1][j];
if(i<3)mat[i+1][j]=!mat[i+1][j];
if(j>0)mat[i][j-1]=!mat[i][j-1];
if(j<3)mat[i][j+1]=!mat[i][j+1];
}
void dfs(int i,int j,int tmp){
if(tmp==step){
flag=judge();
return ;
}
if(flag||i==4)return ;
alter(i,j);
if(j<3)dfs(i,j+1,tmp+1);
else dfs(i+1,0,tmp+1);
alter(i,j);
if(j<3)dfs(i,j+1,tmp);
else dfs(i+1,0,tmp);
}
int main(){
//ifstream in("text.txt");
init_graph();
//test();
for(step=0;step<=16;step++)
{
flag=0;
dfs(0,0,0);
if(flag)break;
}
if(flag)printf("%d\n",step);
else printf("Impossible\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: