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!\n"); */
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\n");
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("\n");
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:\n",tt);
74         if(!dfs(1,1)) printf("NO\n");
75     }
76     return 0;
77 }

 

转载于:https://www.cnblogs.com/zarth/p/6511018.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值