zoukankan      html  css  js  c++  java
  • 数独类型总结

    最近做完了洛谷的P1784 P1074,对数独类型的题目有所感触,现总结如下。

    往往数独类型的题目总是离不开DFS,从P1784说起,该题的要求是完成一个数独,先介绍一下数独的规则,在一个9*9的九宫格中,要求给初始空白格子填入数字(1~9),要求每一列、每一行、每一个3*3的小的九宫格都不能出现重复的数字。我们自然想到使用搜索解决此题,搜索的顺序是搜完一行搜下一行,即每次搜到第9个格子的时候跳转到下一行(这里用0~8循环),使用vx、vy、vk三个二维数组记录每一行、列、小九宫格中是否出现某数,并在搜索时进行回溯,其中需要注意的是如何判断当前的最小格是隶属于哪个小的3*3的九宫格的,我们通过尝试和思考发现对于用0~8表示行列的九宫格,我们用x表示行,用y表示列,那么我们vk[x/3*3+y/3][i]表示这个3*3小的九宫格是否出现了数字i,最后输出九宫格即可

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    int mp[10][10],vx[10][10],vy[10][10],vc[10][10];
    void dfs(int x,int y) {
        if(x==9) {
            for(int i=0; i<9; i++) {
                for(int j=0; j<9; j++) {
                    cout<<mp[i][j]<<" ";
                }
                cout<<endl;
            }
            return ;
        }
        if(y==9) {
            dfs(x+1,0);
            return ;
        }
        if(mp[x][y])
            dfs(x,y+1);
        else for(int i=1; i<=9; i++) {
            if(!vx[x][i] && !vy[y][i] && !vc[x/3*3+y/3][i]) {
                mp[x][y] =i;
                vx[x][i] =1;
                vy[y][i] =1;
                vc[x/3*3+y/3][i] =1;
                dfs(x,y+1);
                mp[x][y]=0;
                vx[x][i] =0;
                vy[y][i] =0;
                vc[x/3*3+y/3][i] =0;
            }
        }
    }
    int main() {
        for(int i=0; i<9; i++) {
            for(int j=0; j<9; j++){
                cin>>mp[i][j];
                vx[i][mp[i][j]]=1;
                vy[j][mp[i][j]]=1;
                vc[i/3*3+j/3][mp[i][j]]=1;
                
            }
        }
        dfs(0,0);
        return 0;
    }

    接下来我们做P1074靶向数独的时候就有了一定的基础了,该题只是在数独上做了一些延伸,即需要每一步记录分数,大体基本不变,只是添加一个分数的参数的话,并在搜索完成后比较最大值,注意如果没有结果,就直接输出-1,那我们不妨将ans一开始定义为-1,这样如果没有答案的话是无法进行最后一步的比较的,就直接输出-1,接下来我们需要打一个表(也可以不打表,但需要一种类似处理所在3*3九宫格位置的方法,留给读者思考),记录不同位置对应靶的分数,这样处理后提交发现T了几个点,我们就需要优化如何优化,似乎无法进行最优化和可行性剪枝。我们思考一下,是否现实中我们在做数独题的时候,我们总是先将数字最多的一个部分先填满,以便后续的推理,这里的优化思想就来源于这种思想,我们需要一个记录每一行元素个数的数组,它同时也要记忆当前的真实行数,并最后从大到小排序,我们从元素最多的一行开始搜索,这样就能完美解决这一问题了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int mp[10][10],vc[10][10],vr[10][10],vk[10][10],ans=-1;
    int biao[10][10]={
    {6,6,6,6,6,6,6,6,6,0},
    {6,7,7,7,7,7,7,7,6,0},
    {6,7,8,8,8,8,8,7,6,0},
    {6,7,8,9,9,9,8,7,6,0},
    {6,7,8,9,10,9,8,7,6,0},
    {6,7,8,9,9,9,8,7,6,0},
    {6,7,8,8,8,8,8,7,6,0},
    {6,7,7,7,7,7,7,7,6,0},
    {6,6,6,6,6,6,6,6,6,0},
    };
    struct node{
        int cnt,v;
        friend    bool operator <(const node& a,const node& b) {
            return a.cnt>b.cnt;
        }
    }s[10];
    void dfs(int x,int y,int sum){
        int temp = s[x].v;
        if(x==9) {
            ans = max(ans,sum);
            return ;
        }
        if(y==9){
            dfs(x+1,0,sum);
            return ;    
        }    
        if(mp[temp][y]) dfs(x,y+1,sum+biao[temp][y]*mp[temp][y]);    
        else for(int i=1; i<=9; i++) {
            if(!vc[temp][i]&&!vr[y][i]&&!vk[temp/3*3+y/3][i]) {
                vc[temp][i]=1;
                vr[y][i]=1;
                vk[temp/3*3+y/3][i]=1;
                mp[temp][y]=i;
                dfs(x,y+1,sum+biao[temp][y]*i);
                vc[temp][i]=0;
                vr[y][i]=0;
                vk[temp/3*3+y/3][i]=0;
                mp[temp][y]=0;
            }
        }
    }
    int main() {
        for(int i=0; i<9; i++) {
            s[i].v=i;
            for(int j=0; j<9; j++) {
                cin>>mp[i][j];
                vc[i][mp[i][j]]=1;
                vr[j][mp[i][j]]=1;
                vk[i/3*3+j/3][mp[i][j]]=1;
                if(mp[i][j]) s[i].cnt++;
            }
        }
        sort(s,s+9);
        dfs(0,0,0);
        cout<<ans;
        return 0;
    } 
  • 相关阅读:
    C++类型转换(字符串)
    GDI+ 中Image::FromStream ,用流的方式显示图像
    mfc对话框序列化实例
    配置android开发环境eclipse获取ADT获取不到(转)
    vs开发错误总结
    MFC获取文件操作
    Android系统架构剖析(转)
    OpenCV 图像采样 插值 几何变换
    C++ char*,char[],string,CString转换
    Simscape Multibody 教程 —— 入门学习
  • 原文地址:https://www.cnblogs.com/delta-cnc/p/12394464.html
Copyright © 2011-2022 走看看