POJ1753 Flip Game
阿新 • • 發佈:2019-01-09
題目連結: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;
}