题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5113
题目分类:dfs
题意:N M K N*M的棋盘 K种颜色 接下来K个数字分别代表每种颜色的数目 要求 相邻的格子的颜色不能相同,输出一种方案就好
题目分析:因为N和M的范围比较小,而且找到一种就好,所以,采用深度优先搜索即可
代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
int N,M,K;
int number[30];
int a[10][10];
bool flag;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
bool check(int i,int j,int val)
{
for(int d=0;d<4;d++)
{
int tx=i+dx[d];
int ty=j+dy[d];
if(tx<=N&&ty<=M&&tx>=1&&ty>=1&&a[tx][ty]==val)
return false;
}
return true;
}
/** 位置是i,j,,剩余的未被访问过的点有left个 */
void dfs(int i,int j,int left)
{
if (flag) return ;
if (left==0)
{
flag=1;
return ;
}
for (int d=1;d<=K;d++)
if (number[d]>(left+1)/2) return ;
if (j>M) dfs(i+1,1,left);
else
{
for (int ii=1;ii<=K;ii++)
{
if (!check(i,j,ii)) continue;
if (number[ii]==0) continue;
number[ii]--;
a[i][j]=ii;
dfs(i,j+1,left-1);
if (flag) return ;
a[i][j]=0;
number[ii]++;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int i,j,t;
scanf("%d",&t);
for(int kase=1;kase<=t;kase++)
{
scanf("%d%d%d",&N,&M,&K);
for (i=1;i<=K;i++)
scanf("%d",&number[i]);
memset(a,0,sizeof(a));
flag=0;
dfs(1,1,N*M);
printf("Case #%d:
",kase);
if(!flag)
printf("NO
");
else
{
printf("YES
");
for(int i=1;i<=N;i++)
{
for(int j=1;j<=M;j++)
{
if(j==1) printf("%d",a[i][j]);
else printf(" %d",a[i][j]);
}
printf("
");
}
}
}
return 0;
}