【计蒜课】 数独 【DFS】

本文介绍了一个使用回溯法解决数独问题的C++程序实现。通过定义状态标记数组跟踪已填充数字,利用递归搜索未知位置并验证每一步填充是否符合数独规则,最终输出解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

蒜头君今天突然开始还念童年了,想回忆回忆童年。他记得自己小时候,有一个很火的游戏叫做数独。便开始来了一局紧张而又刺激的高阶数独。蒜头君做完发现没有正解,不知道对不对? 不知道聪明的你能否给出一个标准答案?

标准数独是由一个给与了提示数字的 9*9 网格组成,我们只需将其空格填上数字,使得每一行,每一列以及每一个3*3 宫都没有重复的数字出现。
这里写图片描述

看代码吧

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
typedef pair<int,int>pii;

const int N = 20;
const int mod = 765431;

int n=9;
char mp[N][N];  //  原图
char opt[N][N]; // 中间图
bool vol[N][N],row[N][N]; //row[i][j] 第i行中已经有j数字,vol[i][j]第i列中已经有j数字
pii P[100];int sz; // 存储所有的未知位置
int flag;

bool check(int now,int val){  // 查询 3*3宫
    pii p = P[now];
    int n=(p.first-1)/3*3;
    int m=(p.second-1)/3*3;

    for(int i=n+1;i<=n+3;i++){
        for(int j=m+1;j<=m+3;j++){
            if(opt[i][j] == val+'0') return false;
        }
    }
    return true;
}

void dfs(int now){
    if(flag) return ;
    if(now==sz) {
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++) {
                if(j!=1) putchar(' ');
                printf("%c",opt[i][j]);
            }
            puts("") ;
        }
        flag=1;
        return ;
    }

    pii p = P[now];
    for(int j=1;j<=9;j++){
        if( !row[p.first][j] && !vol[p.second][j] && check(now,j)){
            row[p.first][j]=1; vol[p.second][j]=1;
            opt[p.first][p.second]=j+'0';
            dfs(now+1);
            row[p.first][j]=0; vol[p.second][j]=0;
            opt[p.first][p.second]=mp[p.first][p.second];
        }
    }
}

int main(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%c",&mp[i][j]);
            opt[i][j]=mp[i][j];
            if(mp[i][j] == '*') {
                P[sz].first=i;
                P[sz++].second=j;
            }else {
                int val=mp[i][j]-'0';
                vol[j][val]=1;
                row[i][val]=1;
            }
        }
        getchar();
    }
    flag=0;
    dfs(0);
    return 0 ;
}

/*
样例
*26******
***5*2**4
***1****7
*3**2*18*
***3*9***
*54*1**7*
5****1***
6**9*7***
******75*


*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值