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))

ACM/ICPC 之 欧拉回路两道(POJ1300-POJ1386)

ACM/ICPC 之 拓扑排序-反向(POJ3687)

ACM/ICPC 之 经典动规(POJ1088-滑雪)

ACM/ICPC 之 递归(POJ2663-完全覆盖+POJ1057(百练2775)-旧式文件结构图)