zoukankan      html  css  js  c++  java
  • 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
    ");
            rep(i,0,n){
                rep(j,0,m){
                    prf("%d",mat[i][j]);
                    if(j==m-1) prf("
    ");
                    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:
    ",++kase);
            su=false;
            dfs(0);
            if(!su) prf("NO
    ");
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
  • 相关阅读:
    理解DOM事件流的三个阶段
    如何在文章/随笔中添加可运行的js代码
    移动端开发所需要的一些资源与小技巧
    媒体查询常用样式表
    微信打开网址添加在浏览器中打开提示
    微信小程序实战–集阅读与电影于一体的小程序项目(八)
    微信小程序实战–集阅读与电影于一体的小程序项目(七)
    微信小程序实战–集阅读与电影于一体的小程序项目(六)
    微信小程序实战–集阅读与电影于一体的小程序项目(五)
    微信小程序实战–集阅读与电影于一体的小程序项目(四)
  • 原文地址:https://www.cnblogs.com/fenice/p/6028917.html
Copyright © 2011-2022 走看看