Why so serious? --[NKU]schindlerlee

2010年1月31日星期日.ural1060-pku1753 枚举状态

2010年1月31日星期日.ural1060-pku1753
Neerc2000中的一题。

题目要求:

给出一个4×4的棋盘的黑白状态,求最少需要多少次翻转(每次翻转会改变当前格和周围四个格的
状态),使棋盘变成全黑或者全白。

貌似是这套题中最水的一题,分析一下复杂度,发现即使完全枚举状态,复杂度也是可以接受的,
然后就枚举吧。

我的存储方法是用一个int型表示棋盘状态,黑1白0,将四行按顺序连起来,写成一个16位整数。


 1 
 2 const int inf = 0x7fffffff;
 3 #define bin(x) (1 <<(x))
 4 int mask = bin(16- 1;
 5 int addr(const int &x,const int &y)
 6 return x * 4 + y; }
 7 int grid;
 8 //http://www.cppblog.com/schindlerlee
 9 bool flip(int press)
10 {
11   int g = grid,i;
12   for (i = 0;i < 16;i++) {
13       if(press & bin(i)) {
14           g ^= bin(i);
15           g ^= bin(i + 4);
16           g ^= bin(i - 4);
17           if (i != 3 && i!= 7 && i != 11 && i!= 15) { g ^= bin(i+1); }
18           if (i != 0 && i!= 4 && i != 8 && i!= 12)  { g ^= bin(i-1); }
19       }
20   }
21   g &= mask;
22   return (g == 0|| (g == mask);
23 }
24 
25 int count(int x)
26 {
27   int res = 0;
28   while(x > 0) {
29       res += x & 1;
30       x >>= 1;
31   }
32   return res;
33 }
34 
35 void ckmin(int & res,int x) { if(x < res) res = x; }
36 int main()
37 {
38   char s[16];
39   int i,j;
40   for (i = 0;i < 4;i++) {
41       scanf("%s\n",s);
42       for (j = 0;j < 4;j++) {
43           if(s[j] == 'b') {
44               grid |= bin(addr(i,j));
45           }
46       }
47   }
48 
49   int res = inf;
50   for (i = 0;i <= mask;i++) {
51       if (flip(i)) {
52           //printf("i=%d\n",i);
53           ckmin(res,count(i));
54       }
55   }
56   if(res == inf) {
57       printf("Impossible\n");
58   }else {
59       printf("%d\n",res);
60   }
61   return 0;
62 }
63 

posted on 2010-01-31 23:31 schindlerlee 阅读(1003) 评论(0)  编辑 收藏 引用 所属分类: 解题报告


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理