POJ 1753 Flip Game (状压+暴力)
Posted Dh_q
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1753 Flip Game (状压+暴力)相关的知识,希望对你有一定的参考价值。
题目链接:http://poj.org/problem?id=1753
题意:
给你一个4*4的棋盘,上面有两种颜色的棋子(一种黑色,一种白色),你一次可以选择一个棋子翻转它(黑色变成白色,同理反之),选择的这枚棋子的上下左右都会被翻动(前提是上下左右都可以被翻动)。问最少可以翻动多少颗棋子,让整个棋盘变成全部黑色或者全部白色。
题解:
4*4一共就16个格子,每个格子都可以是翻或者不翻,那么就是216翻法。
所以就可以用状态压缩的方法来解决。
比如说47。 47的二进制是00101111,我们就可以认为(从右往左)第1,2,3,4,6位是我们选择要翻转的棋子,而为0的位是我们不翻的。这样只要把1~16与4*4的坐标做一个映射就可以知道我们要翻那一个棋子了。把全部棋子翻完之后判断一下是不是全部是一种颜色,是就更新ans。
————————————————————
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 #define pb push_back 14 #define mp make_pair 15 #define ms(a, b) memset((a), (b), sizeof(a)) 16 //#define LOCAL 17 typedef long long LL; 18 const int inf = 0x3f3f3f3f; 19 const int maxn = 100000+10; 20 const int mod = 1e9+7; 21 char input[4][4]; 22 bool color[4][4];//0为白,1为黑 23 void reset()//重新初始化color表 24 { 25 for(int i=0;i<4;i++) 26 for(int j=0;j<4;j++) 27 if(input[i][j] == ‘b‘) color[i][j] = 1; 28 else color[i][j] = 0; 29 } 30 int cnt(int b)//计算b的二进制中右多少个1。 31 { 32 int num = 0; 33 while(b>0){ 34 num++; 35 b&=(b-1); 36 } 37 return num; 38 } 39 void clean(int j)//翻转棋子 40 { 41 int x, y; 42 if(j<4&&j>=0) x=0, y=j; 43 else if(j<8&&j>=4) x=1, y = j-4; 44 else if(j<12&&j>=8) x=2, y = j-8; 45 else x = 3, y = j-12; 46 // printf("%d %d %d\n", j, x, y); 47 color[x][y] = !color[x][y]; 48 if(x-1>=0) color[x-1][y] = !color[x-1][y];//上 49 if(x+1<4) color[x+1][y] = !color[x+1][y];//下 50 if(y-1>=0) color[x][y-1] = !color[x][y-1];//左 51 if(y+1<4) color[x][y+1] = !color[x][y+1];//右 52 } 53 int judge() 54 { 55 bool flag1=1;//全0; 56 bool flag2=1;//全1; 57 58 //判断是不是为全0 59 for(int i=0;i<4;i++){ 60 for(int j=0;j<4;j++){ 61 if(color[i][j]==1) {flag1=0;break;}//如果出现了1就break 62 } 63 } 64 if(flag1==1) return 1;//如果是就直接返回1,即表为全0 65 66 //同理判断是不是为全1 67 for(int i=0;i<4;i++){ 68 for(int j=0;j<4;j++){ 69 if(color[i][j] == 0) {flag2 = 0;break;} 70 } 71 } 72 if(flag2==1) return 1; 73 return 0;//既不是全0,又不是全1,就返回0. 74 } 75 int main() { 76 #ifdef LOCAL 77 freopen("input.txt" , "r", stdin); 78 #endif // LOCAL 79 for(int i=0;i<4;i++) 80 scanf("%s", input[i]); 81 int ans = inf; 82 // for(int i=0;i<16;i++) 83 // clean(i); 84 for(int i=1;i<(1<<16);i++){ 85 reset(); 86 int take = cnt(i); 87 for(int j = 0;j<16;j++){ 88 if(i&(1<<j)){ 89 clean(j); 90 } 91 } 92 if(judge()){ 93 ans = min(ans, take); 94 } 95 } 96 reset();//最后判断初始的时候是否已经是全0或者全1 97 if(judge()) ans = 0; 98 if(ans !=inf) 99 printf("%d\n", ans); 100 else 101 printf("Impossible\n"); 102 return 0; 103 }
以上是关于POJ 1753 Flip Game (状压+暴力)的主要内容,如果未能解决你的问题,请参考以下文章