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 }
View Code

 



以上是关于POJ 1753 Flip Game (状压+暴力)的主要内容,如果未能解决你的问题,请参考以下文章

poj 1753 Flip Game(暴力枚举)

POJ1753 Flip Game(位运算+暴力枚举)

POJ 1753 Flip Game

POJ_1753——Flip Game(枚举)

POJ 1753 Flip Game

POJ1753 Flip Game(bfs枚举)