有一个包含从1到K一共K种颜色的N×M棋盘,使得任意两个相邻的区块不能有相同的颜色(如果它们的上、下、左、右任意一边的颜色与自身颜色不同)。第i种颜色可以被使用Ci次
思路:因为n,m较小,所以可以想到搜索,一行一行的给格子上色,首先这个颜色要有剩余并且不能和上面的和左边的颜色相同。
一个重要的剪枝:当剩下的格子个数为n时,任意一种颜色最多只能为(n+1)/2
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #define ll long long using namespace std; int mp[10][10]; int c[30]; int n,m,k,flag; void dfs(int x,int y,int res) { if(res==0||flag) { flag=1; return; } for(int i=1;i<=k;i++) { if(c[i]>(res+1)/2) return ; } for(int i=1;i<=k;i++) { if(c[i]!=0) { if(mp[x][y-1]!=i&&mp[x-1][y]!=i) { mp[x][y]=i; c[i]--; if(y==m) dfs(x+1,1,res-1); else dfs(x,y+1,res-1); if(flag) return ; c[i]++; } } } } int main() { int t,ca=1; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); memset(mp,0,sizeof(mp)); flag=0; for(int i=1;i<=k;i++) scanf("%d",&c[i]); dfs(1,1,n*m); printf("Case #%d: ",ca++); if(flag) { printf("YES "); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(j==m) printf("%d ",mp[i][j]); else printf("%d ",mp[i][j]); } } else printf("NO "); } return 0; }