2014ACM/ICPC亚洲区北京站-重现赛 [B.Black And White] 涂色DFS

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5113

题目大意:在一个N * M的棋盘里涂色,要求i颜色要涂ci次。ci求和为N * M.

关键思想:从第一个点开始着色,一行一行涂,注意一旦找到答案后面就不必搜,当剩下个数为n时若有种颜色>n/2上取整就不必搜了(!)。

#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <string>
using namespace std;

#define MAXN 1005
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define LL long long
#define PII pair
#define MP make_pair
#define PB push_back

int MAP[7][7];
int c[30];//i种颜色用c[i]次
bool have=false;

int T,N,M,K;

void print(){
    printf("YES\n");
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
            if(j==1)printf("%d",MAP[i][j]);
            else printf(" %d",MAP[i][j]);
        }
        printf("\n");
    }
    return ;
}

void DFS(int x,int y,int tot){
    for(int i=1;i<=K;i++){if(c[i]>(tot+1)/2)return ;}//最坏情况(剩一块矩形)的剪枝,很关键 
    for(int i=1;i<=K;i++){
        if(have)return; 
        if(MAP[x-1][y]!=i&&MAP[x][y-1]!=i&&c[i]!=0){//i种颜色有效 
            MAP[x][y]=i,c[i]--;
            if(x==N&&y==M){
                   have=true;
                print();
                return;
            }
            if(y+1<=M)DFS(x,y+1,tot-1);//未到行尾涂本行 
            else DFS(x+1,1,tot-1);//到行尾涂下一行 
            MAP[x][y]=-1,c[i]++;//恢复 
        }
    }
    return ;
}

int main(){
    scanf("%d",&T);
    for(int Case=1;Case<=T;Case++){
        memset(MAP,-1,sizeof(MAP));//其实按照DFS顺序无需重置 
        scanf("%d%d%d",&N,&M,&K);
        bool flag=true;
        for(int i=1;i<=K;i++){
            scanf("%d",&c[i]);
            if(c[i]>(N*M+1)/2)flag=false;//黑白格都无法满足 
        }
        printf("Case #%d:\n",Case);
        if(!flag){
            printf("NO\n");
            continue;
        }
        have=false;
        DFS(1,1,N*M);
    }
    return 0;
}

 

    原文作者:哇咔咔咔
    原文地址: https://www.cnblogs.com/G-M-WuJieMatrix/p/7425843.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞