题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5113
题意:
有一个n*m的网格,有k种颜色,每种颜色有ci瓶,需要将相邻的网格涂成不同颜色,并且需要将所有颜料用完。问是否可行。
坑点:
adjacent regions竟然是左右相邻,若在行末尾则它的相邻在下一行。(excuse me???,我一直写四个方向
思路:
依照题意可以看成是一条直线填颜色。从第一个格子开始,对接下去的每个格子,dfs一遍各种颜色。剪枝的策略是,当未涂色格子总数+1小于某种颜色此时的数量的一半时,return,很好理解。 对于dfs可能出现的情况有多种,但只要满足一种就可以return。由于存在判断x-1,所以下标最好从0开始
PS:模拟赛时我想就是DFS,同学说超时怎么DFS。。。没人想到剪枝。。。说多了其实还是水平低,姿势不足。
18286272 | 2016-09-18 21:19:06 | Accepted | 5113 | 62MS | 1432K | 1100B | G++ |
#include <cstdio>
#include <cstring>
using namespace std;
bool flag;
int t, n, m, k, color[30], mat[7][7];
void input(){
scanf("%d%d%d", &n, &m, &k);
memset(mat, 0, sizeof(mat));
for(int i=1; i<=k; i++)
scanf("%d", &color[i]);
}
void output(){
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
if(j!=1) printf(" ");
printf("%d", mat[i][j]);
}
printf("\n");
}
}
void dfs(int x, int y, int cnt){
if(cnt==0) {flag=true;return;}
for(int i=1; i<=k; i++){
if((cnt+1)/2 < color[i]) return;
}
for(int i=1; i<=k; i++){
if(color[i] && mat[x-1][y]!=i && mat[x][y-1]!=i){
mat[x][y] = i;
color[i]--;
int curx, cury;
if(y+1>m)
curx=x+1, cury=1;
else
curx=x, cury=y+1;
dfs(curx, cury, cnt-1);
if(flag) return;
mat[x][y] = 0;
color[i]++;
}
}
return;
}
int main(){
scanf("%d", &t);
for(int cas=1; cas<=t; cas++){
input();
printf("Case #%d:\n", cas);
flag = false, dfs(1, 1, n*m);
if(!flag)
printf("NO\n");
else{
printf("YES\n");
output();
}
}
return 0;
}