题意:给定一个N*M的棋盘,要求用K种颜色对每个格染色,相邻的格的颜色不能相同。并且第i种颜色必须恰好出现c[i]次。求是否存在方案,如果存在,输出任意一种。
先把不可行的情况判断出来。
什么情况不可行呢?肯定就是某种颜色要求出现的次数太多了,怎么样算多呢?考虑一种颜色要尽可能多的染上去,我们需要每间隔一个格染一次。
对于一个N*M的棋盘,最多能染的同一种颜色的个数就是L = N*M/2 + (N*M%2==0?0:1)。
意思其实就是棋盘的一半向上取整。
比如2*4的棋盘最多是4个,而3*3的棋盘最多可以5个。
之前由于SB原因交错代码误以为“构造”的代码能AC,实际是WA。。。直接搜吧。。。
多谢 画船听雨 的提醒~
搜索代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int map[10][10];
int T, n, m, k;
struct Color{
int id, cnt;
bool operator < (const Color &A)const{
return cnt > A.cnt;
}
}c[30];
bool ok(int x, int y){
if(x==n) return 1;
if(y==m) return ok(x+1, 0);
for(int i=0; i<k; i++){
if(c[i].cnt){
if(x && map[x-1][y]==i) continue;
if(y && map[x][y-1]==i) continue;
c[i].cnt--;
map[x][y] = i;
if(ok(x, y+1)) return 1;
c[i].cnt++;
}
}
return 0;
}
int main(){
scanf("%d", &T);
for(int t=1; t<=T; t++){
scanf("%d %d %d", &n, &m, &k);
int x = 0;
for(int i=0; i<k; i++){
scanf("%d", &c[i].cnt);
c[i].id = i+1;
if(c[i].cnt>x) x = c[i].cnt;
}
sort(c, c+k);
printf("Case #%d:\n", t);
if((c[0].cnt>(n*m/2+(n*m%2?1:0)))){
puts("NO");
continue;
}
if(ok(0, 0)){
puts("YES");
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(j) putchar(' ');
printf("%d", c[map[i][j]].id);
}
puts("");
}
}
else{
puts("NO");
}
}
return 0;
}