两道枚举题

http://acm.pku.edu.cn/JudgeOnline/problem?id=2965

我用纯枚举做的,216,用了500多ms

 

code1
1 //579MS 2010-05-21 13:57:29
2  #include <stdio.h>
3 #include <string.h>
4
5  const int MK = 1 << 16;
6  //状态转换
7  int swt[20] = { 0,
8 0xf888, 0xf444, 0xf222, 0xf111,
9 0x8f88, 0x4f44, 0x2f22, 0x1f11,
10 0x88f8, 0x44f4, 0x22f2, 0x11f1,
11 0x888f, 0x444f, 0x222f, 0x111f
12 };
13
14  int main()
15 {
16 char ch0[20], ch1[10];
17 int I, K, M;
18 int em = 0, min, hd;
19 while (gets(ch1)) {
20 strcpy(ch0, ch1);
21 I = 3;
22 while (I--) {
23 gets(ch1);
24 strcat(ch0, ch1);
25 }
26 int stu0, stu1;
27 stu0 = 0;
28 //生成初始状态
29   for (I=0; I<16; I++) {
30 if (ch0[I] == '+') stu0 |= 1<<(16-I-1);
31 }
32 min = 0xffffff;
33 //枚举
34   for (em=0; em<MK; em++) {
35 int cnt = 0;
36 stu1 = stu0;
37 for (I=0; I<16; I++) {
38 if ( (1<<I)&em ) {
39 cnt++;
40 stu1 ^= swt[I+1];
41 }
42 }
43 //stu1 = 0 满足条件
44   if (!stu1) {
45 if (cnt < min) { min = cnt; hd = em; }
46 }
47 }
48 printf("%d\n", min);
49 for (I=0; I<16; I++) {
50 if ( (1<<I)&hd ) {
51 printf("%d %d\n", I/4+1, I%4+1);
52 }
53 }
54 }
55 return 0;
56 }
57  

 

再看看No.1的题解

 

代码
1 可以,下面是我两次AC的代码,前一次算是证明吧
2 Problem: 2965 User: huicpc39
3 Memory: 24K Time: 45MS
4 Language: C Result: Accepted
5
6 Source Code
7 #include<stdio.h>
8  int main()
9 {char s[5];int i,j,k,st[4][4];
10  for(i=0;i<4;++i)for(j=0;j<4;++j)st[i][j]=0;
11  for(i=0;i<4;++i)
12 {scanf("%s",s);
13  for(j=0;j<4;++j)if(s[j]=='+')
14 {st[i][j]++;
15  for(k=0;k<4;++k)st[k][j]++;
16  for(k=0;k<4;++k)st[i][k]++;}}
17  for(i=0;i<4;++i)for(j=0;j<4;++j)st[i][j]%=2;
18  for(i=j=0;i<4;++i)for(k=0;k<4;++k)if(st[i][k])j++;
19 printf("%d\n",j);
20  for(i=0;i<4;++i)for(j=0;j<4;++j)if(st[i][j])printf("%d %d\n",i+1,j+1);
21 }
22 按照以上思路,直接生成结果。
23 Source Code
24
25 Problem: 2965 User: huicpc39
26 Memory: 16K Time: 0MS
27 Language: C Result: Accepted
28
29 Source Code
30 #include <stdio.h>
31 int s[16]={0x111f,0x222f,0x444f,0x888f,0x11f1,0x22f2,0x44f4,0x88f8,
32 0x1f11,0x2f22,0x4f44,0x8f88,0xf111,0xf222,0xf444,0xf888};
33 int main()
34 {char c;int i,n,j;
35 n=i=j=0;
36 while((c=getchar())!=EOF)
37 if(c!=10)if(c=='+')n^=s[i++];else ++i;
38 for(i=0;i<16;++i)if(n&(1<<i))++j;printf("%d\n",j);
39 for(i=0;i<16;++i)if(n&(1<<i))printf("%d %d\n",i/4+1,i%4+1);}
40

 

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=1753

枚举第1行的操作,24

然后操作第2-4行,使第i行的操作让i-1行满足全黑或全白。

求出最小的操作数。

 

code3
1 //124K 16MS 2010-05-21 10:50:18
2 //Type:枚举
3 #include <stdio.h>
4 #include <string.h>
5
6 int tsf[20]; //保存2^i
7 const int MK = 0xf; //枚举次数
8 //对每个位置的操作
9 int swt[20] = {0,
10 0x13, 0x27, 0x4E, 0x8C,
11 0x131, 0x272, 0x4E4, 0x8C8,
12 0x1310, 0x2720, 0x4E40, 0x8C80,
13 0x3100, 0x7200, 0xE400, 0xC800
14 };
15
16 void init()
17 {
18 int i;
19 tsf[1] = 1;
20 for (i=2; i<=16; i++) tsf[i] = tsf[i-1] << 1;
21 }
22
23 void Enum(int stu0, int &min)
24 {
25 int I, K, em, cnt, stu;
26 for (em=0; em <= MK; em++) {
27 cnt = 0;
28 stu = stu0;
29 //对第1行的操作
30 for (I=1; I<=4; I++) {
31 if ( em&tsf[I] ) {
32 stu ^= swt[I+12];
33 cnt++;
34 }
35 }
36 //对2-4行的操作
37 for (I=16; I>4; I--) {
38 if ( stu&tsf[I] ) {
39 stu ^= swt[I-4];
40 cnt++;
41 }
42 }
43 if (!stu) {
44 if (min == -1) min = cnt;
45 else if (cnt < min) min = cnt;
46 }
47 }
48 }
49
50 int main()
51 {
52 init();
53 char ch0[20], ch1[20];
54 int I, K;
55 int stu1, stu2;//两个不同的状态
56 int min1, min2;
57 while (gets(ch1)) {
58 I = 3;
59 strcpy(ch0, ch1);
60 while (I--) {
61 gets(ch1);
62 strcat(ch0, ch1);
63 }
64 stu1 = 0;
65 stu2 = 0;
66 //生成两个初始状态
67 for (I=0, K=16; I<16; I++, K--) {
68 if (ch0[I] == 'b') stu1 |= tsf[K];
69 if (ch0[I] == 'w') stu2 |= tsf[K];
70 }
71 min1 = -1;
72 Enum(stu1, min1);
73 min2 = -1;
74 Enum(stu2, min2);
75 if (min1 == -1 && min2 == -1) puts("Impossible");
76 else if (min1 == -1) printf("%d\n", min1);
77 else if (min2 == -1) printf("%d\n", min2);
78 else printf("%d\n", min1 < min2 ? min1 : min2);
79 }
80 return 0;
81 }

 

posted @ 2010-05-21 15:15  superbin  阅读(187)  评论(0编辑  收藏  举报