大体意思是:你需要解决一个类似的问题:有一个包含从1到K一共K种颜色的N×M棋盘,使得任意两个相邻的区块不能有相同的颜色(如果它们的上、下、左、右任意一边的颜色与自身颜色不同)。第i种颜色可以被使用Ci次。
因为n,m都很小所以可以用深搜做,需要注意的问题是当最大的一种颜色的剩余使用次数大于剩余未填充格子加一的一般时,必然会出现两个相同颜色相邻的情况,此时需要剪枝。
#include <iostream>
#include<stdio.h>
using namespace std;
int n,m,k;
int c[100];
int a[10][10];
int flag=0;
void dfs(int x,int y,int left)
{
if(left==0)
{
flag=1;
return;
}
for(int i=0;i<k;i++)
{
if(c[i]>(left+1)/2)
return;
}
for(int i=0;i<k;i++)
{
if(c[i]==0)
continue;
if(x&&a[x-1][y]==i+1)
continue;
if(y&&a[x][y-1]==i+1)
continue;
c[i]--;
a[x][y]=i+1;
if(y<m-1)
dfs(x,y+1,left-1);
else
dfs(x+1,0,left-1);
if(flag==1)
return;
c[i]++;
}
return ;
}
int main()
{
int t;
int cas=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
int i;
for(i=0;i<k;i++)
{
scanf("%d",&c[i]);
}
printf("Case #%d:\n",cas++);
flag=0;
dfs(0,0,n*m);
if(flag==1)
{
printf("YES\n");
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(j)printf(" ");
printf("%d",a[i][j]);
}
printf("\n");
}
}
else
printf("NO\n");
}
return 0;
}