HDU 5113 Black And White ( 2014 北京区预赛 B 、搜索 + 剪枝 )

题目链接

题意 : 给出 n * m 的网格、要你用 k 种不同的颜色填给出的网格、使得相邻的格子颜色不同、若有解要输出具体的方案

分析 :

看似构造、实则搜索、手构构半天没有什么好想法

直接搜就行了、注意加上剪枝

当剩下格子不足以让剩下颜色数量最多的颜色产生间隔的话则返回

具体也很好实现、即 max( 剩下的最多数量的那种颜色的数量 ) > ( 还剩多少格子 + 1 ) / 2

#include<bits/stdc++.h>
using namespace std;

const int maxn = (int)1e2 + 10;

int rem[maxn];
int num[maxn];
int G[maxn][maxn];
int n, m, k;
int len;

bool Check(int tot)
{
    for(int i=1; i<=k; i++)
        if(rem[i] > (tot+1)/2)
            return false;
    return true;
}

bool DFS(int r, int c, int cur)
{
    if(cur == 0) return true;
    if(!Check(cur)) return false;
    for(int i=1; i<=k; i++){
        if(rem[i] > 0 && G[r][c-1] != i && G[r-1][c] != i){
            rem[i]--;
            G[r][c] = i;

            int rr, cc;
            if(c + 1 > m) rr = r+1, cc = 1;
            else rr = r, cc = c + 1;

            if(DFS(rr, cc, cur-1)) return true;

            G[r][c] = 0;
            rem[i]++;
        }
    }return false;
}

int main(void)
{
    int nCase;
    scanf("%d", &nCase);
    for(int T=1; T<=nCase; T++){

        memset(G, 0, sizeof(G));

        scanf("%d %d %d", &n, &m, &k);

        len = n * m;

        for(int i=1; i<=k; i++){
            scanf("%d", &num[i]);
            rem[i] = num[i];
        }

        printf("Case #%d:
", T);
        if(DFS(1, 1, len)){
            puts("YES");
            int idx = 1;
            for(int i=1; i<=n; i++){
                for(int j=1; j<=m; j++){
                    if(j == 1) printf("%d", G[i][j]);
                    else printf(" %d", G[i][j]);
                }puts("");
            }

        }else puts("NO");


    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/qwertiLH/p/9736047.html