数独类型总结

最近做完了洛谷的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;
} 

 

原文链接: https://www.cnblogs.com/ashdr/p/12394464.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    数独类型总结

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/370980

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月3日 上午10:31
下一篇 2023年3月3日 上午10:31

相关推荐