poj_1735_Flip Game

来源:互联网 发布:微信中淘宝链接打不开 编辑:程序博客网 时间:2024/05/18 08:08

一道需要活跃思维的搜索题,当然,对于2^16 的复杂度也可以枚举来做.


题目大意: http://poj.grids.cn/practice/1753/

给一个4*4的棋盘,上面有黑子 (用字符'b'表示) 和白子 (用字符'w'表示) .可以选择棋子翻转,每翻转一个棋子,其周围四个棋子也会被翻转(边角情况正常处理),问最少翻转多少次可以让棋盘全黑或全白.

解题思路:

一看只有16个格子,首先想到了枚举~:

for(int i=0;i<1;++i)

.

.

.

16层......后来一想这么写多丢人......所以还是搜索吧,bfs和dfs基本都没有问题,因为求最少步数,所以还是bfs比较适合.

把棋盘看做简单的0-1矩阵,对每一个位置取反时也会对周围4个位置取反,对一个数取反可以写做: n=n^1; .那么从什么状态开始搜素呢?~

将0-1矩阵合并,看成一个二进制数,那么他的范围仅仅为 0-0xffff 也就是一共仅有 0xfff 种状态.对每一位翻转,可以求出其状态转移方程:

   当前状态a ^ 转移状态i (i为翻转的位置),a==0 时结束,每个位置会有其单独的翻转状态.比如 0,0 位:

    1100      1000      0000      0000    周围四个位置取反.  

接下来就是么每一位的转移状态i的处理. 将矩阵每一位编号.

    F E D C      B A 9 8      7 6 5 4      3 2 1 0  

那么,其上下左右就为: 上: -4 下:+4 左:-1 右: +1 求转移状态的源码就为:


    void build() {          memset(no,0,sizeof(no));          int num=1;          for(int i=N;i>0;--i) {              for(int j=1;j<=4;++j) {                  int tx=i*4-j;                  no[num]=1<<(tx);                  for(int k=0;k<4;++k) {                      int x=tx+dbit[k];                      if(x<0||x>15)                          continue;                      if((tx+4)%4==0&&(x+4)%4==3) {                          continue;                      }                      if((tx+4)%4==3&&(x+4)%4==0) {                          continue;                      }                      no[num]=no[num]+(1<<x);                  }                       num++;              }          }      }  

求出转移状态后,就以每一个点为起点bfs 即可:

    #include <myhead.h>      const int N=4;      const int s=0xffff;      const int t=0;      const int dbit[]={-4,1,+4,-1};      struct Node {          int m,num;          int i;      };      bool _hash[100000];      char a[N+1][N+1];      int no[20];      Node node;            void build() {          memset(no,0,sizeof(no));          int num=1;          for(int i=N;i>0;--i) {              for(int j=1;j<=4;++j) {                  int tx=i*4-j;                  no[num]=1<<(tx);                  for(int k=0;k<4;++k) {                      int x=tx+dbit[k];                      if(x<0||x>15)                          continue;                      if((tx+4)%4==0&&(x+4)%4==3) {                          continue;                      }                      if((tx+4)%4==3&&(x+4)%4==0) {                          continue;                      }                      no[num]=no[num]+(1<<x);                  }                       num++;              }          }      }            bool init() {          for(int i=0;i<N;++i) {              if(scanf("%s",a[i])==EOF) {                  return false;              }          }          memset(_hash,0,sizeof(_hash));          node.i=node.m=node.num=0;          int m=0;          for(int i=N-1;i>=0;--i) {              for(int j=N-1;j>=0;--j) {                  if(a[i][j]=='b') {                      node.m=node.m+(1<<m);                  }                  m=m+1;              }          }          return true;      }            void bfs() {          queue<Node> q;          q.push(node);          while(!q.empty()) {              Node tmp=q.front();              q.pop();              if(tmp.m==s||tmp.m==0) {                  printf("%d\n",tmp.num);                  return ;              }              node.num=tmp.num+1;              for(int i=1;i<=16;++i) {                  if(tmp.i!=i) {                      node.i=i;                      node.m=(tmp.m^no[i]);                      if(!_hash[node.m]) {                          _hash[node.m]=true;                          q.push(node);                      }                  }              }          }          printf("Impossible");      }            int main()      {          build();          init();          bfs();          return 0;      }  


原创粉丝点击