HDU 5113 Black And White 回溯+剪枝

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5113

Black And White

Time Limit: 2000/2000 MS (Java/Others)
Memory Limit: 512000/512000 K (Java/Others)
#### 问题描述 > In mathematics, the four color theorem, or the four color map theorem, states that, given any separation of a plane into contiguous regions, producing a figure called a map, no more than four colors are required to color the regions of the map so that no two adjacent regions have the same color. > — Wikipedia, the free encyclopedia > > In this problem, you have to solve the 4-color problem. Hey, I’m just joking. > > You are asked to solve a similar problem: > > Color an N × M chessboard with K colors numbered from 1 to K such that no two adjacent cells have the same color (two cells are adjacent if they share an edge). The i-th color should be used in exactly ci cells. > > Matt hopes you can tell him a possible coloring.

输入

The first line contains only one integer T (1 ≤ T ≤ 5000), which indicates the number of test cases.

For each test case, the first line contains three integers: N, M, K (0 < N, M ≤ 5, 0 < K ≤ N × M ).

The second line contains K integers ci (ci 0), denoting the number of cells where the i-th color should be used.

It’s guaranteed that c1 + c2 + · · · + cK = N × M .

输出

For each test case, the first line contains “Case #x:”, where x is the case number (starting from 1).

In the second line, output “NO” if there is no coloring satisfying the requirements. Otherwise, output “YES” in one line. Each of the following N lines contains M numbers seperated by single whitespace, denoting the color of the cells.

If there are multiple solutions, output any of them.

样例输入

4
1 5 2
4 1
3 3 4
1 2 2 4
2 3 3
2 2 2
3 2 3
2 2 2

样例输出

Case #1:
NO
Case #2:
YES
4 3 4
2 1 2
4 3 4
Case #3:
YES
1 2 3
2 3 1
Case #4:
YES
1 2
2 3
3 1

题意

给你n*m的方格,你要用k种颜色去填,每种颜色要填ci次,并且要保证没有任意两个相邻的格子有相同的颜色,构造一种可行方法,如果不存在输出-1.

题解

直接暴力回溯+剪枝,当没填的颜色中同种颜色数量超过(剩余格子+1)/2的时候,不可能合法。

代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf

typedef int LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=10000000000000000LL;
const double eps=1e-9;

const double PI = acos(-1.0);

//start----------------------------------------------------------------------

const int maxn=33;

int n,m,k;
int arr[maxn];
int mat[7][7];
bool su;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};

bool ok(int x,int y,int color){
    for(int i=0;i<4;i++){
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(nx<0||nx>=n||ny<0||ny>=m) continue;
        if(mat[nx][ny]==color) return false;
    }
    return true;
}

void dfs(int sta){
    if(sta==n*m){
        su=true;
        prf("YES\n");
        rep(i,0,n){
            rep(j,0,m){
                prf("%d",mat[i][j]);
                if(j==m-1) prf("\n");
                else prf(" ");
            }
        }
        return;
    }

    ///剪枝
    int ma=0;
    for(int i=1;i<=k;i++) ma=max(ma,arr[i]);
    if(ma>(n*m-sta+1)/2) return;

    ///回溯
    int x=sta/m,y=sta%m;
    for(int i=1;i<=k;i++){
        if(arr[i]==0) continue;
        if(ok(x,y,i)){
            mat[x][y]=i;
            arr[i]--;
            dfs(sta+1);
            if(su) return;
            arr[i]++;
            mat[x][y]=-1;
        }
    }
}

void init(){
    clr(mat,-1);
}

int main() {
    int tc,kase=0;
    scf("%d",&tc);
    while(tc--) {
        init();
        scf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=k;i++){
            scf("%d",&arr[i]);
        }
        prf("Case #%d:\n",++kase);
        su=false;
        dfs(0);
        if(!su) prf("NO\n");
    }
    return 0;
}

//end-----------------------------------------------------------------------
posted @ 2016-11-04 02:15  fenicnn  阅读(187)  评论(0编辑  收藏  举报