『題解』POJ1753 Flip Game
阿新 • • 發佈:2018-12-22
題意描述
有\(4 \times 4\)的正方形,每個格子要麼是黑色,要麼是白色,當把一個格子的顏色改變(黑\(\to\)白 或 白\(\to\)黑)時,其周圍上下左右(如果存在的話)的格子的顏色也被反轉,問至少反轉幾個格子可以使\(4 \times 4\)的正方形變為純白或者純黑?
分析
對於每一個格子,只有兩個狀態,將它翻轉一次與翻轉奇數次效果是一樣的,翻轉零次與翻轉偶數次的效果是一樣的。
因為只有\(16\)個格子,選擇\(0\)個,\(1\)個,\(2\)個\(\cdots16\)個所有的情況有
C[0][16]+C[1][16]+C[2][16]+...+C[15][16]+C[16][16]=2^16
列舉不會超時,所以我們可以用遞迴的思想模擬0-16
重迴圈,分別表示選擇翻轉的棋子個數。
AC程式碼
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; bool bits[16], flag=false; inline void resever(int n) {//翻轉 int x=n/4,y=n%4; for (int i=max(0,y-1); i<min(y+2,4); i++) bits[x*4+i]=!bits[x*4+i]; if (x!=0) bits[(x-1)*4+y]=!bits[(x-1)*4+y]; if (x!=3) bits[(x+1)*4+y]=!bits[(x+1)*4+y]; } inline bool judge() {//判斷是否一致 bool ini=bits[0]; for (int i=1; i<16; i++) if (ini!=bits[i]) return 0; return 1; } inline void solve(int maxx, int now, int step) { if (maxx==step) {//翻轉完最後一枚棋子 if (judge()) {//滿足狀態 flag=1; printf("%d\n",maxx); } return ; } for (int i=now; i<16; i++) {//從上次翻轉位置繼續 resever(i);//翻轉i solve(maxx, i+1, step+1); if (flag) return ;//找到答案,返回 resever(i);//恢復原來狀態 } } int main() { char str[4][4]; for (int i=0; i<4; i++) { cin>>str[i]; for (int j=0; j<4; j++) bits[i*4+j]=(str[i][j]=='b') ? 1 : 0; } for (int i=0; i<=16; i++)//i 為要翻轉的棋子個數 solve(i, 0, 0); if (!flag) printf("Impossible\n");//沒有找到答案 return 0; }