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 }