您的位置:首页 > 其它

hdu 5113 Black And White(dfs+剪枝)

2015-09-17 17:34 465 查看
题目链接:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: