[POJ1753]Flip Game
题目链接:http://poj.org/problem?id=1753
读完题,可以很自然地想到一种搜索。既然每颗只有翻或不翻两种选择,那我们直接列出16颗棋子翻与不翻的所有情况就可以了$ O(2^{16}*判断) $
但是会不会有更科学的解决方法呢?观察可以发现,如果我们确定了第一行,便可以通过翻转第二行的棋子使第一行颜色相同,同理,第三行对第二行,第四行对第三行也是同理。经过以上处理,前三行颜色相同,第四行显然无法在行内自我调整,可以直接判断。所以我们只需要通过搜索确定第一行的四个棋子。
综上我们得出第二种方法,复杂度$ O(2^4*12*判断) $近似$O(2^8*判断)$
事实上这时我初三的代码,现在的我已经弱爆了
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int INF = 2147483647; 6 char G[10][10]; 7 int g[10][10], tmp[10][10], Ans = INF; 8 void flip(int a, int b){ 9 g[a][b] ^= 1; 10 g[a + 1][b] ^= 1; 11 g[a - 1][b] ^= 1; 12 g[a][b + 1] ^= 1; 13 g[a][b - 1] ^= 1; 14 } 15 int work(int flag, int step){ 16 int ans = 0; 17 for (int i = 2; i <= 4; i++){ 18 for (int j = 1; j <= 4; j++){ 19 if (g[i - 1][j] != flag){ 20 flip(i, j); 21 ans++; 22 } 23 } 24 } 25 for (int i = 1; i <= 4; i++) 26 if (g[4][i] != flag) 27 return INF; 28 return ans + step; 29 } 30 void search(int k, int ans){ 31 if (k > 4){ 32 for (int i = 1; i <= 4; i++) 33 for (int j = 1; j <= 4; j++) 34 tmp[i][j] = g[i][j]; 35 Ans = min(work(0, ans), Ans); 36 for (int i = 1; i <= 4; i++) 37 for (int j = 1; j <= 4; j++) 38 g[i][j] = tmp[i][j]; 39 Ans = min(work(1, ans), Ans); 40 for (int i = 1; i <= 4; i++) 41 for (int j = 1; j <= 4; j++) 42 g[i][j] = tmp[i][j]; 43 return; 44 } 45 search(k + 1, ans); 46 flip(1, k); 47 search(k + 1, ans + 1); 48 flip(1, k); 49 } 50 int main(){ 51 for (int i = 1; i <= 4; i++) 52 scanf("%s", G[i] + 1); 53 for (int i = 1; i <= 4; i++) { 54 for (int j = 1; j <= 4; j++) { 55 if (G[i][j] == 'w') g[i][j] = 1; 56 else g[i][j] = 0; 57 } 58 } 59 search(1, 0); 60 if (Ans < INF) printf("%d", Ans); 61 else printf("Impossible"); 62 return 0; 63 }