题目链接:点击打开链接
题目大意:翻转游戏是在一个矩形的4x4域上进行的,它的每一个16个方块上都有两面正面的棋子。每片的一边是白色的,另一边是黑色的,每一块都是黑色或白色的。每一轮你掷3到5个,这样就把他们的上侧的颜色从黑色变为白色,反之亦然。
根据以下规则,
1.每一轮都选择被翻转的棋子:选择16块中的任意一个。
2.把选中的部分和所有相邻的部分都翻转到左边,右边,顶部,和选择的部分(如果有的话)。
向输出文件写入单个整数,即从给定位置获得游戏目标所需的最少轮数。如果目标最初是实现的,那么就写0。如果不可能实现目标,那么就写“不可能”的单词
解题思路:
因为一个棋子只有两种状态,要么黑要么白,要使得整个棋盘(本题中是4*4的棋盘)都是一种颜色,最多只要16步就好了,一个棋子实际上只要翻转一次,整个棋盘最多要翻转2^16次。
翻转次数不是很大,我们只要枚举出所有情况就好了,用dfs即可。
解题代码:
#include<iostream>
using namespace std;
bool map[16][16]= {false};
bool flag=false;
int step;
int a[6]= {-1,1,0,0,0},b[6]= {0,0,-1,1,0}; //左右上中下
bool judge() //判断是否全部同色
{
for(int i=1; i<=4; i++) //五个位置,除开自身,只要判断四个
for(int j=1; j<=4; j++)
{
if(map[i][j]!=map[1][1])
return false;
}
return true;
}
void flip(int row,int col) //翻转棋子
{
for(int i=0; i<=4; i++)
map[row+a[i]][col+b[i]]=!map[row+a[i]][col+b[i]];
return;
}
void dfs(int row,int col, int deep)
{
if(deep==step) //判断是否从map[1][1]翻转到当前位置
{
flag=judge();
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()
{
char fir;
for(int i=1; i<=4; i++)
for(int j=1; j<=4; j++)
{
cin>>fir;
if(fir=='b') map[i][j]=true; //把黑棋标记为true,白旗为false
}
for(step=0; step<=16; step++) //根据思路,一共只要走4*4(16)步
{
dfs(1,1,0);
if(flag) break;
}
if(flag)
cout<<step<<endl;
else
cout<<"Impossible"<<endl;
return 0;
}
~step by step