题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5113
解题思路:
题目大意:
给你一个N*M的棋盘,要求用K种颜色对每个格染色,相邻的格的颜色不能相同。并且第i种颜色必须恰好出现c[i]次。求是否存在该方案,如果存在,输出任意一种。
算法思想:
因为n,m都比较小,所以直接搜索即可,但是需要加一个剪枝,因为当剩下的容量为n时,任意一种颜色最多只能为n*m/2+(n*m%2?
1:0),当任意一种颜色的数量超过这个值时,就输出NO,剩下的暴力搜就可以了。。。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int g[10][10];
int n,m,k;
struct Color{
int id, cnt;
bool operator < (const Color &a)const{
return cnt > a.cnt;
}
}c[30];
bool dfs(int x,int y){
if(x > n)
return 1;
if(y > m)
return dfs(x+1, 1);
for(int i = 1; i <= k; i++){
if(c[i].cnt){
if(g[x-1][y] == i)
continue;
if(g[x][y-1] == i)
continue;
c[i].cnt--;
g[x][y] = i;
if(dfs(x, y+1))
return 1;
c[i].cnt++;
}
}
return 0;
}
int main(){
int T,t = 1;
scanf("%d", &T);
while(T--){
memset(g,0,sizeof(g));
scanf("%d%d%d",&n,&m,&k);
for(int i = 1; i <= k; i++){
scanf("%d", &c[i].cnt);
c[i].id = i;
}
sort(c+1,c+k+1);
printf("Case #%d:\n", t++);
if(c[1].cnt > (n*m/2+(n*m%2?1:0))){
printf("NO\n");
continue;
}
if(dfs(1, 1)){
printf("YES\n");
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(j != 1)
printf(" ");
printf("%d", c[g[i][j]].id);
}
printf("\n");
}
}
else
printf("NO\n");
}
return 0;
}