ACM/ICPC 之 枚举(POJ1681-画家问题+POJ1166-拨钟问题)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM/ICPC 之 枚举(POJ1681-画家问题+POJ1166-拨钟问题)相关的知识,希望对你有一定的参考价值。
POJ1681-画家问题
枚举的经典例题,枚举第一行即可,其余行唯一。
1 //画家问题,y表示黄色,w表示白色,怎样让墙上所有方格为y,操作类似熄灯问题poj1222 2 //memory 136K Time: 297 Ms 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 9 #define INF 0x3f3f3f3f 10 #define MAX 20 11 12 char m[MAX][MAX]; 13 int n,ans,sum; 14 int map[MAX][MAX],cpmap[MAX][MAX],p[MAX]; 15 int move[4][2] = {{1,0},{-1,0},{0,1},{0,-1}}; 16 17 void paint(int x,int y) 18 { 19 sum++; 20 cpmap[x][y] = !cpmap[x][y]; 21 for(int i=0;i<4;i++) 22 { 23 int tx = x+move[i][0]; 24 int ty = y+move[i][1]; 25 if(tx>=0 && tx<n && ty>=0 && ty<n) 26 cpmap[tx][ty] ^= 1; 27 } 28 } 29 30 /*尝试绘画*/ 31 int test_paint() 32 { 33 int i,j; 34 for(i=0;i<n;i++) //第一行 35 if(p[i]) 36 paint(0,i); 37 for(i=1;i<n;i++) //其余行唯一 38 { 39 for(j=0;j<n;j++) 40 { 41 if(!cpmap[i-1][j]) 42 paint(i,j); 43 } 44 } 45 //判断最后一行是否符合 46 int flag = 1; 47 for(i=0;i<n;i++) 48 if(!cpmap[n-1][i]) 49 { 50 flag = 0;break; 51 } 52 return flag; 53 } 54 55 int main() 56 { 57 int T; 58 int i,j; 59 scanf("%d",&T); 60 while(T--) 61 { 62 memset(p,0,sizeof(p)); 63 ans = INF; 64 scanf("%d",&n); 65 for(i=0;i<n;i++) 66 scanf("%s",m[i]); 67 //字符-转换为-0与1 68 for(i=0;i<n;i++) 69 for(j=0;j<n;j++) 70 if(m[i][j] == ‘y‘) 71 map[i][j] = 1; 72 else 73 map[i][j] = 0; 74 75 p[0] = -1; 76 int res; 77 while(1) 78 { 79 sum = 0; 80 memcpy(cpmap,map,sizeof(map)); 81 /*二进制枚举第一行所有画法*/ 82 p[0]++; 83 res = p[0]/2; 84 j=1; 85 while(res) 86 { 87 p[j-1] = 0; 88 p[j]++; 89 res = p[j++]/2; 90 } 91 if(p[n]) 92 break; 93 if(test_paint()) 94 if(ans > sum) 95 ans = sum; 96 } 97 if(ans == INF) 98 printf("inf\n"); 99 else 100 printf("%d\n",ans); 101 } 102 return 0; 103 }
POJ1166-拨钟问题
分析后枚举所有可能情况。
//暴力枚举-熄灯问题变形-拨钟问题,给出九个钟的时针位置(3,6,9,12)-(1,2,3,0)-将他们调到12点 即 //Memory 134K Time: 0 Ms #include<iostream> #include<cstring> #include<cstdio> using namespace std; int sclock[10]; //source-clock int pc[10]; //调好后时针位置 int main() { int j; for (j = 1; j <= 9; j++) scanf("%d",&sclock[j]); int i[10]; //枚举所有九种拨法的情况-每种拨法最多3次 (第四次相当于没有拨动) //4^9种情况 for (i[1] = 0; i[1] < 4; i[1]++) for (i[2] = 0; i[2] < 4; i[2]++) for (i[3] = 0; i[3] < 4; i[3]++) for (i[4] = 0; i[4] < 4; i[4]++) for (i[5] = 0; i[5] < 4; i[5]++) for (i[6] = 0; i[6] < 4; i[6]++) for (i[7] = 0; i[7] < 4; i[7]++) for (i[8] = 0; i[8] < 4; i[8]++) for (i[9] = 0; i[9] < 4; i[9]++) { pc[1] = (sclock[1] + i[1] + i[2] + i[4]) % 4; pc[2] = (sclock[2] + i[1] + i[2] + i[3] + i[5]) % 4; pc[3] = (sclock[3] + i[2] + i[3] + i[6]) % 4; pc[4] = (sclock[4] + i[1] + i[4] + i[5] + i[7]) % 4; pc[5] = (sclock[5] + i[1] + i[3] + i[5] + i[7] + i[9]) % 4; pc[6] = (sclock[6] + i[3] + i[5] + i[6] + i[9]) % 4; pc[7] = (sclock[7] + i[4] + i[7] + i[8]) % 4; pc[8] = (sclock[8] + i[5] + i[7] + i[8] + i[9]) % 4; pc[9] = (sclock[9] + i[6] + i[8] + i[9]) % 4; int sum = 0; for (j = 1; j <= 9; j++) sum += pc[j]; if (!sum) { for (j = 1; j <= 9;j++) while (i[j]--) printf("%d ",j); printf("\n"); return 0; } } return 0; }
以上是关于ACM/ICPC 之 枚举(POJ1681-画家问题+POJ1166-拨钟问题)的主要内容,如果未能解决你的问题,请参考以下文章
ACM/ICPC 之 昂贵的聘礼-最短路解法(POJ1062)
ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083))