ACM/ICPC 之 枚举(POJ1681-画家问题+POJ1166-拨钟问题+POJ1054-讨厌的青蛙)

  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-拨钟问题

  分析后枚举所有可能情况。

 1 //暴力枚举-熄灯问题变形-拨钟问题,给出九个钟的时针位置(3,6,9,12)-(1,2,3,0)-将他们调到12点 即 
 2 //Memory 134K Time: 0 Ms
 3 
 4 #include<iostream>
 5 #include<cstring>
 6 #include<cstdio>
 7 using namespace std;
 8 
 9 int sclock[10];    //source-clock
10 int pc[10];    //调好后时针位置
11 
12 int main()
13 {
14     int j;
15     for (j = 1; j <= 9; j++)
16         scanf("%d",&sclock[j]);
17     int i[10];    //枚举所有九种拨法的情况-每种拨法最多3次 (第四次相当于没有拨动)
18     //4^9种情况
19     for (i[1] = 0; i[1] < 4; i[1]++)
20     for (i[2] = 0; i[2] < 4; i[2]++)
21     for (i[3] = 0; i[3] < 4; i[3]++)
22     for (i[4] = 0; i[4] < 4; i[4]++)
23     for (i[5] = 0; i[5] < 4; i[5]++)
24     for (i[6] = 0; i[6] < 4; i[6]++)
25     for (i[7] = 0; i[7] < 4; i[7]++)
26     for (i[8] = 0; i[8] < 4; i[8]++)
27         for (i[9] = 0; i[9] < 4; i[9]++)
28         {
29         pc[1] = (sclock[1] + i[1] + i[2] + i[4]) % 4;
30         pc[2] = (sclock[2] + i[1] + i[2] + i[3] + i[5]) % 4;
31         pc[3] = (sclock[3] + i[2] + i[3] + i[6]) % 4;
32         pc[4] = (sclock[4] + i[1] + i[4] + i[5] + i[7]) % 4;
33         pc[5] = (sclock[5] + i[1] + i[3] + i[5] + i[7] + i[9]) % 4;
34         pc[6] = (sclock[6] + i[3] + i[5] + i[6] + i[9]) % 4;
35         pc[7] = (sclock[7] + i[4] + i[7] + i[8]) % 4;
36         pc[8] = (sclock[8] + i[5] + i[7] + i[8] + i[9]) % 4;
37         pc[9] = (sclock[9] + i[6] + i[8] + i[9]) % 4;
38 
39         int sum = 0;
40         for (j = 1; j <= 9; j++)
41             sum += pc[j];
42         if (!sum)
43         {
44             for (j = 1; j <= 9;j++)
45                 while (i[j]--)
46                     printf("%d ",j);
47             printf("\n");
48             return 0;
49         }
50         }
51     return 0;
52 }

 

 

 

 

  POJ1054-讨厌的青蛙

 

 1 //Flog直线等步长踩稻子(array),找出踩过最多的一条Flog路径
 2 //Memory 172K Time: 47 Ms
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<algorithm>
 7 using namespace std;
 8 
 9 #define min(x,y) ((x)>(y)?(y):(x))
10 #define MAX 5005
11 
12 struct Node {
13     int x, y;
14 }map[MAX];    //踩过路径
15 
16 int row, col, length;
17 int n, maxlen = 2;
18 
19 bool operator < (const Node &a, const Node &b)    //重载全局运算符 <,以满足binary_search()与sort()处理Node的需要
20 {
21     //二重排序-行列序
22     if (a.x == b.x)    return a.y < b.y;
23     return a.x < b.x;
24 }
25 
26 /*延长路径-判定该路径是否成立*/
27 void extend(Node second, int cx, int cy)
28 {
29     Node t;
30     t.x = second.x + cx;
31     t.y = second.y + cy;
32     while (t.x >= 1 && t.x <= row && t.y >= 1 && t.y <= col)
33     {
34         if (!binary_search(map, map + n, t))//没有find-不成立
35         {
36             length = 0;
37             break;
38         }
39         //find-成立
40         length++;
41         t.x += cx;
42         t.y += cy;
43     }
44     if (length > maxlen)
45         maxlen = length;
46 }
47 
48 int main()
49 {
50     scanf("%d%d%d", &row, &col, &n);
51     for (int i = 0; i<n; i++)
52         scanf("%d%d", &map[i].x, &map[i].y);
53 
54     sort(map, map + n);
55     for (int i = 0; i < n; i++)
56         for (int j = i + 1; j < n; j++)
57         {
58             length = 2;
59             int cx = map[j].x - map[i].x;    //横步长
60             int cy = map[j].y - map[i].y;    //纵步长
61             int px = map[i].x - cx;        //(px,py)为假想跳跃起始位置
62             int py = map[i].y - cy;
63             
64             if (px >= 1 && px <= row && py >= 1 && py <= col)
65                 continue;    //已访问此路径或路径不存在
66             
67             px = map[i].x + (maxlen - 1)*cx;
68             py = map[i].y + (maxlen - 1)*cy;
69             if (px > row)    break;        //纵向须跳跃的最小距离超过row-遍历第一跳跃点
70             if (py > col || py < 1)    continue; //横向须跳跃的最小距离超过col-遍历第二跳跃点
71             extend(map[j], cx, cy);    //极值无误-尝试拓展
72         }
73 
74     if (maxlen == 2) maxlen = 0;    //没有最长路径
75     printf("%d\n", maxlen);
76     return 0;
77 }

 

你可能感兴趣的:(ACM/ICPC 之 枚举(POJ1681-画家问题+POJ1166-拨钟问题+POJ1054-讨厌的青蛙))