数独

数独填空1

给出测试组数
再给出未填时的99数独情况
输出填完的数独情况
要求每行和每列1-9只能出现一次,且局部3
3格中,也满足,而且3*3中每个数字需要出现一次
传送门
思路,多设了3个数组,用来记录出现的次数
然后从左上角开始搜索,从左到右,满了就到下一行的第一个,直到走到最后一行后,因为是dfs,所以记得回溯

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=10;
int G[N][N];

//对于01两种状态的,建议使用bool数据类型,因为bool只有一位,而int又4位,浪费空间
bool hang[N][N],lie[N][N],dyg[N][N],flag;//hang[i][x]表示第i行数字x是否用过,lie[j][x]表示第j列数字x是否用过,dyg[k][x]表示9个3*3的单元格里第k个单元格是否用过
void print(){
    for(int i=0;i<9;i++){
        for(int j=0;j<9;j++){
            printf("%d",G[i][j]);
        }
        putchar('\n');
    }
}
void dfs(int x,int y){
    if(flag)return;//针对循环过程会输出多个数独表和多循环
    if(x==9){//全部都搜索完了
        flag=1;
        print();
        return;
    }else{//继续搜索
        if(G[x][y]){//该位置不需要填数字
            if(y<8)dfs(x,y+1);//向右
            else dfs(x+1,0);//一行已经都搜过了,进行下一行搜索
        }else{//该位置需要填数字
            for(int i=1;i<=9;i++){
                if(!hang[x][i]&&!lie[y][i]&&!dyg[x/3*3+y/3][i]){//如果i这个数字
                    G[x][y]=i;//保存搜到的数
                    hang[x][i]=lie[y][i]=dyg[x/3*3+y/3][i]=true;//标记
                    if(y<8)dfs(x,y+1);
                    else dfs(x+1,0);
                    G[x][y]=0;//回溯
                    hang[x][i]=lie[y][i]=dyg[x/3*3+y/3][i]=false;
                }
            }
        }
    }
}

int main(){
    int t;
    cin>>t;
    while(t--){
        memset(hang,false,sizeof(hang));
        memset(lie,false,sizeof(lie));
        memset(dyg,false,sizeof(dyg));
        flag=0;
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                scanf("%1d",&G[i][j]);//输入没有包含空格,每次只输入一个数字
                if(G[i][j]!=0){
                    int v=G[i][j];
                    hang[i][v]=true;
                    lie[j][v]=true;
                    dyg[i/3*3+j/3][v]=true;//分成了9个单元格
                }
            }
        }
        dfs(0,0);//从第1行第一列开始搜索
    }
    return 0;
}

舞蹈链求数独

转载于:https://www.cnblogs.com/Emcikem/p/11516866.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值