zoukankan      html  css  js  c++  java
  • poj1753 Flip Game

    题意:4*4的正方形,每个格子有黑白两面,翻转格子使得4*4个格子显示全黑或全白,翻转要求:选中的那个格子,以及其上下左右相邻的格子(如果存在)要同时翻转。输出最小的达到要求的翻转次数或者Impossible(如果不可能)

    题目链接:http://poj.org/problem?id=1753

    分析:因为每个格子只有黑白两面,所以对于每个格子来说,要么不翻转,要么翻转一次,因为翻转奇数次结果和翻转一次得到的效果是一样的,而翻转偶数次得到的效果和不翻转是一样的,则总共有16个格子,最多要翻转16次,每个格子有黑白两种颜色,假设每一次面临的4*4正方形代表一个状态,则总共有2^16种状态,可以用16位二进制数表示,每一位1代表'b'(白),0代表'w'(黑)。当状态为(0或者65535)时则达到要求。

    注意:1.因为只用求最少次数,用bfs做,将每一个没有访问到的状态 (用vis[]数组标记) 加入到队列中,如果游戏无法完成,状态必定会形成循环,由于重复状态不会再次入队,所以最后的队列一定会是空队列。当队列为空时说明此时还未达到要求,则是Impossible

            2.二进制运算,翻转某一个格子即指将1变成0,0变成1.这里可以用异或运算的性质,1^0=1,0^0=0;所以只用将需要翻转的那个格子对应的16位二进制数的位置为1,其他不翻转的格子对应的16位二进制数的位置为0得到一个数和当前状态的16位二进制数异或即可得到翻转后的状态。

    例如:

    bwwb
    bbwb
    bwwb
    bwww

       的状态可以表示为1001 1101 1001 1000 (二进制),如果我现在要翻转第一行第一个格子,则可以用此二进制数和1100 1000 0000 0000 异或,则可以得到下一个状态next=1001 1101 1001 1000 ^  1100 1000 0000 0000 = 0101 0101 1001 1000

    即:

    wbwb
    wbwb
    bwwb
    bwww

    可以得到转换每一个格子需要异或的二进制数(十进制表示):

    int change[16] = {

    51200,58368,29184,12544,

    35968,20032,10016,4880,

    2248,1252,626,305,

    140,78,39,19

    };

    代码:

     1 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};  
     2 void init()  
     3 {  
     4     int i,j,x,y,t,temp;  
     5     for(i=0;i<4;++i)  
     6     {  
     7         for(j=0;j<4;++j)  
     8         {  
     9             temp = 0;   
    10             temp ^= (1<<(15 - ( i*4 + j )));  
    11             for(t=0;t<4;++t)  
    12             {  
    13                 x = i + dir[t][0];  
    14                 y = j + dir[t][1];  
    15                 if(x<0 || y<0 || x>3 || y>3)  
    16                     continue;  
    17                 temp ^= (1<<((3-x)*4+3-y));  
    18             }  
    19             cout<<temp<<" ";  
    20         }  
    21         cout<<endl;  
    22     }  
    23 }  

    完整代码1:(bfs+bit)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<cmath>
     5 #include<string>
     6 #include<cstring>
     7 #include<algorithm>
     8 #include<vector>
     9 using namespace std;
    10 char m[4][4];
    11 //int di[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
    12 struct Node
    13 {
    14     int state,step;
    15 }nod[100000];
    16 int vis[100000];
    17 /*
    18 int change[16] =   //16种状态转换,对应4*4的翻子位置 方法2.直接异或得到状态
    19 {
    20      51200,58368,29184,12544,
    21      35968,20032,10016,4880,
    22      2248,1252,626,305,
    23      140,78,39,19
    24 };
    25 */
    26 int getChang(int stat,int x,int y)  //方法1.翻转需要翻转的格子
    27 {
    28     int tp=stat;
    29     tp^=(1<<(15-x*4-y));
    30     if(x>0) tp^=(1<<(15-(x-1)*4-y)); //
    31     if(x<3) tp^=(1<<(15-(x+1)*4-y)); //
    32     if(y>0) tp^=(1<<(15-x*4-y+1));  //
    33     if(y<3) tp^=(1<<(15-x*4-y-1));  //
    34     return tp;
    35 }
    36 int bfs(Node cur)
    37 {
    38     queue<Node>q;
    39     q.push(cur);
    40     Node next;
    41     vis[cur.state]=1;
    42 
    43     while(!q.empty())
    44     {
    45         cur=q.front();
    46         q.pop();
    47         if(cur.state==0||cur.state==65535)  //判断是否全黑/全白
    48             return cur.step;
    49         for(int i=0;i<4;i++)
    50         {
    51             for(int j=0;j<4;j++)
    52             {
    53                 next.state=getChang(cur.state,i,j);  //按部得到状态
    54                 //next.state=cur.state^change[i]; //直接异或得到状态 (循环要改为for(int i=0;i<16;i++) )
    55                 next.step=cur.step+1;
    56                 if(next.state==0||next.state==65535)
    57                     return next.step;
    58                 if(vis[next.state])  //是否已经入队过
    59                     continue;
    60                 q.push(next);
    61                 vis[next.state]=1;
    62             }
    63         }
    64     }
    65     return -1;
    66 }
    67 int main()
    68 {
    69     memset(vis,0,sizeof(vis));
    70     int tmp=0;
    71     for(int i=0;i<4;i++)
    72     {
    73         cin>>m[i];
    74         for(int j=0;j<4;j++)
    75         {
    76             if(m[i][j]=='b')
    77                 tmp+=(1<<(15-4*i-j));
    78         }
    79     }
    80     Node cur;
    81     cur.state=tmp;
    82     cur.step=0;
    83     int ans=bfs(cur);
    84     if(ans==-1)
    85         printf("Impossible
    ");
    86     else
    87         printf("%d
    ",ans);
    88     return 0;
    89 }

     完整代码2:(dfs)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<queue>
     5 #include<vector>
     6 #include<map>
     7 #include<algorithm>
     8 #include<string>
     9 #include<cstring>
    10 using namespace std;
    11 int mp[10][10];
    12 int step;
    13 bool flag;
    14 int judge()
    15 {
    16     for(int i=0;i<4;i++)
    17         for(int j=0;j<4;j++)
    18             if(mp[i][j]!=mp[0][0])
    19                return 0;
    20     return 1;
    21 }
    22 void flip(int x,int y)
    23 {
    24     mp[x][y]=!mp[x][y];
    25     if(x>0) mp[x-1][y]=!mp[x-1][y];
    26     if(x<3) mp[x+1][y]=!mp[x+1][y];
    27     if(y>0) mp[x][y-1]=!mp[x][y-1];
    28     if(y<3) mp[x][y+1]=!mp[x][y+1];
    29 }
    30 void dfs(int x,int y,int deep)
    31 {
    32     if(deep==step)
    33     {
    34         flag=judge();
    35         return;
    36     }
    37     if(flag||x>=4)
    38         return;
    39     flip(x,y);
    40     if(y<3)
    41         dfs(x,y+1,deep+1);
    42     else
    43         dfs(x+1,0,deep+1);
    44     flip(x,y);
    45     if(y%4<3)
    46         dfs(x,y+1,deep);
    47     else
    48         dfs(x+1,0,deep);
    49     return;
    50 }
    51 int main()
    52 {
    53     string s;
    54     flag=0;
    55     for(int i=0;i<4;i++)
    56     {
    57         cin>>s;
    58         for(int j=0;j<4;j++)
    59             if(s[j]=='b')
    60                mp[i][j]=1;
    61     }
    62     for(step=0;step<=16;step++)
    63     {
    64         dfs(0,0,0);
    65         if(flag)
    66             break;
    67     }
    68     if(flag)
    69         printf("%d
    ",step);
    70     else
    71         printf("Impossible
    ");
    72     return 0;
    73 }
    View Code
  • 相关阅读:
    springboot+mybatisplus使用xml找不到mapper的解决办法
    PDF转换成Word文档
    Mybatis-Plus增删改查
    Redis 常用命令
    Java 获取两个List<String>中不同的数据
    controller 返回界面 中文乱码
    Navicat已经成功连接,密码忘记的解决方案
    List数组指定切割
    xml字符串转换成Map
    Java 前一个月的最后一天日期计算
  • 原文地址:https://www.cnblogs.com/tristatl/p/5859595.html
Copyright © 2011-2022 走看看