题目链接:点击打开链接
题意描述:给一个n*m的棋盘,现在有k种颜色的涂料,每种涂料可以使用ai次。求能否找出一种方案,给所有的格子染色,保证相邻的格子之间颜色不同。如果存在给出任意一种解决方案;否则输出NO
解题思路:dfs+剪枝
由于题目中棋盘最大为5×5所以可以考虑使用dfs,染色问题有一个结论貌似是:(剩余的格子的数量+1)>= 任意一种涂料的个数,否则染色必然失败。因此我们可以通过这个性质进行剪枝,此题如果不剪枝会TLE
代码:
#include <cstdio> #include <cstring> using namespace std; int n,m,k; int c[41]; int g[6][6]; bool check(int x,int y,int cc){ if(x-1>=1&&g[x-1][y]==cc) return false; if(y-1>=1&&g[x][y-1]==cc) return false; return true; } bool dfs(int x,int y){ for(int i=1;i<=k;i++) if((n*m-(m*(x-1)+y-1)+1)/2<c[i]) return false; for(int i=1;i<=k;i++){ if(c[i]>0&&check(x,y,i)) { c[i]--; g[x][y]=i; if(x==n&&y==m) return true; if(y+1<=m){ if(dfs(x,y+1)) return true; } else { if(x+1<=n) if(dfs(x+1,1)) return true; } c[i]++; g[x][y]=-1; } } return false; } int main(){ int T; scanf("%d",&T); for(int t=1;t<=T;++t){ scanf("%d%d%d",&n,&m,&k); memset(g,-1,sizeof(g)); for(int i=1;i<=k;i++) scanf("%d",&c[i]); printf("Case #%d:\n",t); if(dfs(1,1)){ printf("YES\n"); for(int i=1;i<=n;++i){ for(int j=1;j<m;++j) printf("%d ",g[i][j]); printf("%d\n",g[i][m]); } } else printf("NO\n"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-10 17:40:21