• 【DFS】hdu 5113 Black And White


    题目描述:

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

     

    中文大意:

    尝试给 N×M 大小的棋盘上色,颜色有 K 种选择(从 1 到 K 编号),要求相邻两个格子的颜色不同。

    属于四色问题的变形,但与“四色问题”不同的是,当前颜色有 K 种,且每种颜色有数量限制。

    思路:

    从棋盘的位置 0 开始,进行颜色的填涂。

    每个位置,都有 k 种选择。其中,用完的,或者已经被四周单元格填涂过的颜色,不做考虑。

    在当前位置填涂完毕后,继续尝试填涂下一位置,如此往复,直至棋盘填涂完毕。

    注意剪枝,不然会超时。

    剪枝情况:某种颜色的剩余数量 > 剩余格子数量的二分之一。

     

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,m,k;
    int nums[26];//各颜色的数量 
    bool have_result;//是否有解 
    int maps[5][5];//记录棋盘颜色信息 
    int end_maps[5][5];//最终的解 
    
    int dir[4][2] = {{0,-1}, {0,1}, {-1,0}, {1,0}};
    
    //检查该位置是否可以填涂颜色 color
    //即四周没有填涂该颜色 
    bool check(int row, int col, int color){
        for(int j=0;j<4;j++){
            int nx = col + dir[j][0];
            int ny = row + dir[j][1];
            
            if(nx>=0 && nx<m && ny>=0 && ny<n){
                if(maps[ny][nx] == color){
                    return false;
                }
            }
        }
        return true;
    }
    
    //index:棋盘位置 
    void dfs(int index){
        //剪枝: 
        //1.已经有了合适的答案 
        if(have_result){
            return;
        }
        //2.找到一组解 
        if(index == n*m){
            have_result = true;
            memcpy(end_maps, maps, sizeof(maps));
            return;
        }
        //3.当某种颜色的剩余数量 > 剩余格子数量的二分之一时
        //即肯定有两个相邻格子要填涂一样的颜色 
        for(int i=1;i<=k;i++){
            if(nums[i] > (n*m-index+1)/2){
                return;
            }
        }
        
        //尝试在当前位置填涂这 k 种颜色
        for(int i=1;i<=k;i++){
            //当前颜色已经用完 
            if(nums[i] == 0){
                continue;
            }
            
            int col = index % m;
            int row = index / m;
            //四周没有当前颜色 
            if(check(row, col, i)){
                maps[row][col] = i;
                nums[i]--;
                dfs(index+1);
                //maps 和 nums 为公共数据,需要及时恢复,避免回溯时已被修改
                maps[row][col] = 0;
                nums[i]++;
            }
        }
    }
    
    int main(){
        int t;
        scanf("%d", &t);
        for(int x=1;x<=t;x++){
            scanf("%d %d %d", &n, &m, &k);
            //各颜色的数量 
            for(int i=1;i<=k;i++){
                scanf("%d", &nums[i]);
            }
            
            have_result = false;
            memset(maps, 0, sizeof(maps));
            dfs(0);
            
            printf("Case #%d:
    ", x);
            if(!have_result){
                printf("NO
    ");
            }
            else{
                printf("YES
    ");
                for(int i=0;i<n;i++){
                    for(int j=0;j<m;j++){
                        if(j != 0){
                            printf(" ");
                        }
                        printf("%d", end_maps[i][j]);
                    }
                    printf("
    ");
                }
            }
        }
    } 
    作者:老干妈就泡面
    本文版权归作者和博客园共有,欢迎转载,但请给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    使用 typeof bar === "object" 来确定 bar 是否是对象的潜在陷阱是什么?
    null和undefined的区别?
    JS中 [] == ![]结果为true,而 {} == !{}却为false
    kaptcha验证码使用
    Java Web应用中获取用户请求相关信息,如:IP地址、操作系统、浏览器等信息
    springboot注解
    算法思想
    数据结构
    springboot设置接口超时
    mybatis动态sql
  • 原文地址:https://www.cnblogs.com/bjxqmy/p/14450153.html
Copyright © 2020-2023  润新知