POJ1753-FlipGame

第一种方法:先枚举第一行的16种情况,然后依次翻转第2、3、4行分别使上一行为同一色,然后判断第四行,若仍为同一色,则比较翻转次数;否则Impossible.

Problem: 1753   User: wjinkun
Memory: 352K   Time: 16MS
Language: GCC   Result: Accepted
  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 int piece[4][4],temp_piece[4][4];
  5 
  6 void flip(int i,int j)
  7 {
  8     temp_piece[i][j]=!temp_piece[i][j];
  9 
 10     if(i-1>=0)
 11         temp_piece[i-1][j]=!temp_piece[i-1][j];
 12 
 13     if(i+1<=3)
 14         temp_piece[i+1][j]=!temp_piece[i+1][j];
 15 
 16     if(j-1>=0)
 17         temp_piece[i][j-1]=!temp_piece[i][j-1];
 18 
 19     if(j+1<=3)
 20         temp_piece[i][j+1]=!temp_piece[i][j+1];
 21 }
 22 
 23 int main()
 24 {
 25     int i,j,k,min=17,n;
 26 
 27     for(i=0; i<4; i++)               //b1w0
 28         {
 29             for(j=0; j<4; j++)
 30                 if(getchar()=='b')
 31                     piece[i][j]=1;
 32                 else
 33                     piece[i][j]=0;
 34 
 35             getchar();
 36         }
 37 
 38 //全翻至白
 39     for(i=0; i<16; i++)          //第一行2^4=16种情况
 40         {
 41             memcpy(temp_piece,piece,sizeof(piece));
 42             n=0;
 43 
 44             for(j=0; j<4; j++)
 45                 if((i&(1<<j))>>j)       //第一行第j个翻转
 46                     {
 47                         flip(0,j);
 48                         n++;
 49                     }
 50 
 51             for(j=1; j<4; j++)         //翻转第2.3.4行分别使上一行为都为白
 52                 for(k=0; k<4; k++)
 53                     if(temp_piece[j-1][k])
 54                         {
 55                             flip(j,k);
 56                             n++;
 57                         }
 58 
 59             for(j=0; j<4; j++)       //检查第4行是否都为白
 60                 if(temp_piece[3][j])
 61                     {
 62                         n=17;
 63                         break;
 64                     }
 65 
 66             if(n<min)
 67                 min=n;
 68         }
 69 
 70 //全翻至黑
 71     for(i=0; i<16; i++)
 72         {
 73             memcpy(temp_piece,piece,sizeof(piece));
 74             n=0;
 75 
 76             for(j=0; j<4; j++)
 77                 if((i&(1<<j))>>j)
 78                     {
 79                         flip(0,j);
 80                         n++;
 81                     }
 82 
 83             for(j=1; j<4; j++)
 84                 for(k=0; k<4; k++)
 85                     if(!temp_piece[j-1][k])
 86                         {
 87                             flip(j,k);
 88                             n++;
 89                         }
 90 
 91             for(j=0; j<4; j++)
 92                 if(!temp_piece[3][j])
 93                     {
 94                         n=17;
 95                         break;
 96                     }
 97 
 98             if(n<min)
 99                 min=n;
100         }
101 
102     if(n!=17)
103         printf("%d\n",min);
104     else
105         printf("%s","Impossible\n");
106 
107     return 0;
108 }

第二种方法是看了别人的思路后写的,枚举+bfs:用unsigned short记录棋子的2^16=65536种情况,将初始状态入队列,再出队列判断是否是0或65535(同一色),若是则输出,否则将由该状态翻转1次的入队列,依次类推。关键减少时间的步骤是要记录最大的棋子,比如a状态由翻转2,5两个棋子得到,那么a的下一次翻转只需从6开始,前面的情况一定出现过,因此需记录5,减少重复。

Problem: 1753   User: wjinkun
Memory: 588K   Time: 16MS
Language: GCC   Result: Accepted
 1 #include <stdio.h>
 2 unsigned short queue[65536][2];   //[0]记录状态,[1]记录下一次起始位置
 3 unsigned short step[65536];       //步数
 4 
 5 int main()
 6 {
 7     int rear=1,top=0,i,j,temp;
 8 
 9     for(i=0; i<4; i++)               //b1w0
10         {
11             for(j=0; j<4; j++)
12                 if(getchar()=='b')
13                     queue[0][0]|=1<<(i*4+j);
14 
15             getchar();
16         }
17 
18 
19     while(rear>top)
20         {
21             if(queue[top][0]==0||queue[top][0]==65535)
22                 {
23                     printf("%d\n",step[queue[top][0]]);
24                     return 0;
25                 }
26             else
27                 {
28                     for(i=queue[top][1]; i<16; i++)
29                         {
30                             temp=queue[top][0];
31                             temp^=1<<i;
32 
33                             if(i%4!=0)
34                                 temp^=1<<(i-1);
35 
36                             if(i%4!=3)
37                                 temp^=1<<(i+1);
38 
39                             if(i-4>=0)
40                                 temp^=1<<(i-4);
41 
42                             if(i+4<16)
43                                 temp^=1<<(i+4);
44 
45                             queue[rear][0]=temp;
46                             queue[rear++][1]=i+1;
47                             step[temp]=step[queue[top][0]]+1;
48                         }
49 
50                     top++;
51                 }
52         }
53 
54     printf("%s\n","Impossible\n");
55     return 0;
56 }

posted on 2012-08-28 12:01  wjinkun  阅读(119)  评论(0编辑  收藏  举报

导航