版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Fitz1318/article/details/86146329
题目链接:http://poj.org/problem?id=1753
大致题意:翻转游戏在一个长方形的4x4场地上进行,在其16个方格中分别放置双面棋子。每个棋子的一面是白色,另一面是黑色,每个都是黑色或白色朝上。每一轮你翻转3至5个,将被翻转的棋子的颜色从黑色改为白色,反之亦然。根据以下规则,每轮选择要翻转的棋子: ①选择16个中的任何一个②将所选择棋子以及该棋子相邻的上下左右棋子翻转(如果有的话)
解题思路:
①对于每个格子,它要么反转0次,要么反转1次(当然,它的邻格子也跟着反转),因为它反转偶数次和反转0次的效果是一样的,同理反转奇数次的效果和反转1次的效果是一样的。
②由于只有16个格子,我们可以选择0个格子,1个格子,2个格子,3个格子......进行反转,总的选择情况为
③当0个格子被反转时,看它是否为纯色,否则选择一个格子进行反转(有16种选择),看反转后是否为纯色,否则选择两个格子进行反转(有120种选择),看反转后是否为纯色。
④只要③中有纯色出现,就停止③,输出相应的被选择的格子个数,结束。如果16个格子都被翻转了,还是没变成纯色,则输出“Impossible”。
⑤分别写一个判断是否一个颜色的judge函数和一个翻转flip函数,在这里可以将棋盘扩大成6*6,这样保证最中间的4*4,及题目所给的棋盘的每一个棋子都有上下左右棋子。
⑥设所要翻转的棋子为(i,j),则对这个棋子进行翻转时需要同时翻动(i-1,j).(i+1,j)(i,j)(i,j-1)(i,j+1),这五个棋子,所以在最初可以设置一个r={-1,1,0,0,0},c={0,0,-1,1,0},便于翻转函数flip的编写。
0 | 1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|---|
0 | ||||||
1 | 棋子 | 棋子 | 棋子 | 棋子 | ||
2 | 棋子 | 棋子 | 棋子 | 棋子 | ||
3 | 棋子 | 棋子 | 棋子 | 棋子 | ||
4 | 棋子 | 棋子 | 棋子 | 棋子 | ||
5 |
AC代码:
#include <iostream>
using namespace std;
bool chess[6][6] = {0};
bool flag;
int deep;
int step;
int row[5] = {-1,1,0,0,0};
int col[5] = {0,0,-1,1,0};
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 flip(int r,int c)//翻棋
{
for(int i=0; i<5; i++)
chess[r+row[i]][c+col[i]] =!chess[r+row[i]][c+col[i]];
}
void dfs(int r,int c,int deep)
{
if(deep == step){
flag = judge();
return;
}
if(flag||r==5)
return;
//翻棋
flip(r,c);
if(c<4)
dfs(r,c+1,deep+1);
else
dfs(r+1,1,deep+1);
//不符合则翻回来
flip(r,c);
if(c<4)
dfs(r,c+1,deep);
else
dfs(r+1,1,deep);
return;
}
int main()
{
char temp;
int i,j;
for(i=1; i<5; i++){
for(j=1; j<5;j++){
cin >> temp;
if(temp == 'b')
chess[i][j] = 1;
}
}
for(step=0; step<16; step++){
dfs(1,1,0);
if(flag)
break;
}
if(flag)
cout << step << endl;
else
cout << "Impossible" << endl;
return 0;
}