題目鏈接:http://poj.org/problem?id=1753
大致題意:翻轉游戲在一個長方形的4x4場地上進行,在其16個方格中分別放置雙面棋子。每個棋子的一面是白色,另一面是黑色,每個都是黑色或白色朝上。每一輪你翻轉3至5個,將被翻轉的棋子的顏色從黑色改爲白色,反之亦然。根據以下規則,每輪選擇要翻轉的棋子: ①選擇16箇中的任何一個②將所選擇棋子以及該棋子相鄰的上下左右棋子翻轉(如果有的話)
解題思路:①每個棋子翻轉的次數爲0(偶數)次或1(奇數)次。這個棋盤最多走16步,共種狀態。將黑白色看成0、1。
②以全黑或全白作爲根節點去搜索樹葉看看是否有輸入時的狀態,枚舉所有狀態,直到找到目標狀態。樹的深度就是所要翻轉的最小次數。
③分別寫一個判斷是否一個顏色的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;
}