• 数独(luogu 1784)


    题目描述

    数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1-9,不重复。每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的。

    芬兰一位数学家号称设计出全球最难的“数独游戏”,并刊登在报纸上,让大家去挑战。

    这位数学家说,他相信只有“智慧最顶尖”的人才有可能破解这个“数独之谜”。

    据介绍,目前数独游戏的难度的等级有一道五级,一是入门等级,五则比较难。不过这位数学家说,他所设计的数独游戏难度等级是十一,可以说是所以数独游戏中,难度最高的等级他还表示,他目前还没遇到解不出来的数独游戏,因此他认为“最具挑战性”的数独游戏并没有出现。

    输入输出格式

    输入格式:

     

    一个未填的数独

     

    输出格式:

     

    填好的数独

     

    输入输出样例

    输入样例
    8 0 0 0 0 0 0 0 0 
    0 0 3 6 0 0 0 0 0 
    0 7 0 0 9 0 2 0 0 
    0 5 0 0 0 7 0 0 0 
    0 0 0 0 4 5 7 0 0 
    0 0 0 1 0 0 0 3 0 
    0 0 1 0 0 0 0 6 8 
    0 0 8 5 0 0 0 1 0 
    0 9 0 0 0 0 4 0 0
    输出样例
    8 1 2 7 5 3 6 4 9 
    9 4 3 6 8 2 1 7 5 
    6 7 5 4 9 1 2 8 3 
    1 5 4 2 3 7 8 9 6 
    3 6 9 8 4 5 7 2 1 
    2 8 7 1 6 9 5 3 4 
    5 2 1 9 7 4 3 6 8 
    4 3 8 5 2 6 9 1 7 
    7 9 6 3 1 8 4 5 2

    有趣的一个益智游戏,但用人脑做却太麻烦了
     

     解析:

    • 这道题完全是可以用深搜暴力解出,关键是注意三个限制条件:
    1. 每行不重
    2. 每列不重
    3. 每宫不重
    • 既然有这三个条件的约束,那我们就要想办法将这些约束条件表示出来,我们用 m 记录已填的数量
    1. 行(hang):m / 9
    2. 列(lie):m % 9
    3. 九宫格的行起始:hang/3 * 3
    4. 九宫格的列起始:lie/3 * 3
     
    代码如下:
    #include<stdio.h>
    #include<cstdlib>
    using namespace std;
    int h[10],l[10],tri[10],mp[10][10];
    
    bool canplace(int hang,int lie,int num)
    {
        int h_gon= hang/3 * 3;
        int l_gon= lie/3 * 3;
        for(int i=0 ; i<9 ; ++i)
            if(mp[hang][i]==num || mp[i][lie]==num) return 0;
        
        for(int i=0 ; i<3 ; ++i)
            for(int j=0 ; j<3 ; ++j)
                if(mp[h_gon+i][l_gon+j] == num) return 0;
            
        return 1;            
    }
    
    void output()
    {
        for(int i=0 ; i<9 ; ++i)
            for(int j=0 ; j<9 ; ++j)
                printf("%d%c",mp[i][j], j == 8?'
    ':' ');
        exit(0);        
    }
    
    
    void dfs(int m)
    {
        int hang=m/9;
        int lie=m%9;
        if(m==81) output();
        if(mp[hang][lie]>0) dfs(m+1);
        else 
        {
            for(int i=1;i<=9;++i)
            {
                if(canplace(hang,lie,i))
                {
                    mp[hang][lie]=i;
                    dfs(m+1);
                    mp[hang][lie]=0;
                }    
            }
        }
    }
    
    int main()
    {
        for(int i=0 ; i<9 ; ++i)
        {
            for(int j=0 ; j<9 ; ++j){
                scanf("%d",&mp[i][j]);
            }
        }
        dfs(0);
        return 0;
    }

     updated:2018-10-31

    为靶形数独做铺垫

    code

    #include<stdio.h>
    #include<cstdlib>
    using namespace std;
    int mp[10][10];
    bool line[10][10],list[10][10],gon[10][10];
    
    int Get(int x,int y) {
        if(x<3) {
            if(y<3) return 1;
            else if(y<6) return 2;
            else return 3; 
        }
        else if(x<6) {
            if(y<3) return 4;
            else if(y<6) return 5;
            else return 6;
        }
        else if(x<9) {
            if(y<3) return 7;
            else if(y<6) return 8;
            else return 9;
        }
    }
    
    void output()
    {
        for(int i=0 ; i<9 ; ++i)
            for(int j=0 ; j<9 ; ++j)
                printf("%d%c",mp[i][j], j == 8?'
    ':' ');
        exit(0);
    }
    
    void dfs(int m)
    {
        int x=m/9;
        int y=m%9;
        if(m==81) output();
        if(mp[x][y]>0) dfs(m+1);
        else 
        {
            for(int i=1;i<=9;++i)
            {
                int wh=Get(x,y);
                if(!line[x][i] && !list[y][i] && !gon[wh][i])
                {
                    line[x][i]=list[y][i]=gon[wh][i]=1;
                    mp[x][y]=i;
                    dfs(m+1);
                    line[x][i]=list[y][i]=gon[wh][i]=0;
                    mp[x][y]=0;
                }    
            }
        }
    }
    
    int main()
    {
        for(int i=0 ; i<9 ; ++i)
        {
            for(int j=0 ; j<9 ; ++j) {
                int x;
                scanf("%d",&x);
                mp[i][j]=x;
                line[i][x]=1;
                list[j][x]=1;
                gon[Get(i,j)][x]=1;
            }
        }
        dfs(0);
        return 0;
    }
    从0到1很难,但从1到100很容易
  • 相关阅读:
    北京周末去哪儿 —— 玉渊潭
    Linux 添加中文字体库,解决Java 生成中文水印不显示问题
    海淀驾校拿本过程
    IOS 微信返回按钮事件控制弹层关闭还是返回上一页
    java 将mysql中Blob类型转为字符串或数字
    echarts 技巧自己的一些记录
    java发送post请求,使用multipart/form-data的方式传递参数,可实现服务器间文件上传功能(转)
    java 调用webservice接口wsdl,推荐使用wsdl2java,放弃wsimport
    北京周末去哪儿 —— 香山
    北京周末去哪儿 —— 百望山森林公园
  • 原文地址:https://www.cnblogs.com/qseer/p/9425008.html
Copyright © 2020-2023  润新知