zoukankan      html  css  js  c++  java
  • HDU 5113 Black And White

    题目链接:HDU-5113

    题意为给一个n*m的矩阵染色,颜色i有( d_{i} )种颜色。相邻块颜色不能重复。

    思路:首先最值得注意的是n和m均不大于5。这种数据范围显然是要搜索。但是直接dfs会超时。

    所以需要用如下性质剪枝:

    任一颜色剩余数目不能超过剩余格子数的一半。

    这条性质很容易理解:可以想象一下在1*12的矩阵中,放7个颜色,无论如何会有两个相邻。

    这条性质可以记住,方便以后使用。

    代码如下:

     1 #include<cstdio>
     2 #include<set>
     3 #include<map>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<iostream>
     8 using namespace std;
     9 typedef long long LL;
    10 
    11 const int MAXN = 30;
    12 int n,m,k;
    13 int d[MAXN];
    14 int color[10][10];
    15 bool adj(int x,int y,int c)
    16 {
    17     if(c==color[x+1][y]) return false;
    18     if(c==color[x-1][y]) return false;
    19     if(c==color[x][y+1]) return false;
    20     if(c==color[x][y-1]) return false;
    21     return true;
    22 }
    23 bool dfs(int x,int y)
    24 {
    25     int xx,yy;
    26     if(y==m) xx=x+1,yy=1;
    27     else xx=x,yy=y+1;
    28     /* if(x==1 && y==2 && color[1][1]==2)
    29      *     printf("Debug!
    "); */
    30     int maxd=0;
    31     for(int i=1;i<=k;i++) maxd=max(d[i],maxd);
    32     int last=n*m-(x-1)*m-y+1;
    33     if(maxd>(last+1)/2) return false; //剪枝
    34     for(int i=k;i>=1;i--)
    35     {
    36         if(d[i] && adj(x,y,i))
    37         {
    38             color[x][y]=i;
    39             d[i]--;
    40             if(x==n && y==m)
    41             {
    42                 printf("YES
    ");
    43                 for(int ii=1;ii<=n;ii++)
    44                 {
    45                     for(int jj=1;jj<=m;jj++)
    46                     {
    47                         printf("%d",color[ii][jj]);
    48                         if(jj!=m) printf(" ");
    49                     }
    50                     printf("
    ");
    51                 }
    52                 return true;
    53             }
    54             if(dfs(xx,yy)) return true;
    55             d[i]++;
    56         }
    57     }
    58     color[x][y]=0;
    59     return false;
    60 }
    61 int main()
    62 {
    63 #ifdef LOCAL
    64     freopen("in.txt","r",stdin);
    65 #endif
    66     int t;
    67     scanf("%d",&t);
    68     for(int tt=1;tt<=t;tt++)
    69     {
    70         memset(color,0,sizeof(color));
    71         scanf("%d%d%d",&n,&m,&k);
    72         for(int i=1;i<=k;i++) scanf("%d",&d[i]);
    73         printf("Case #%d:
    ",tt);
    74         if(!dfs(1,1)) printf("NO
    ");
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    【UOJ 121】Hzwer的陨石
    【UOJ 666】古老的显示屏
    【UOJ 222】正方形二分型
    【UOJ 654】虫洞问题
    【UOJ 226】最近公共祖先
    【UOJ 92】有向图的强连通分量
    poj2139 Floyd
    poj1631 dp,最长上升子序列
    poj1065&1548 dp,最长上升子序列,偏序与反偏序
    poj1458(裸LCS)
  • 原文地址:https://www.cnblogs.com/zarth/p/6511018.html
Copyright © 2011-2022 走看看