[搜索算法][1] DFS

Introduction

数独是一项非常简单的任务。如图所示,将具有9行9列的正方形表划分为9个较小的正方形3x3。在某些单元格中写入从1到9的十进制数字。其他单元格为空。目标是用1到9的十进制数字填充空单元格,每个单元格一位数字,以这种方式在每一行,每一列和每个标记的3x3子正方形中都显示1到9的所有数字。编写程序以解决给定的Sudoku任务。
在这里插入图片描述

Input

输入数据将从测试用例的数量开始。对于每个测试用例,紧跟着表的行的是9行。在每一行上,给出了一个准确的9位十进制数字的字符串,对应于该行中的单元格。如果单元格为空,则用0表示。

Output

对于每个测试用例,您的程序应以与输入数据相同的格式打印解决方案。空单元格必须根据规则进行填充。如果解决方案不是唯一的,则程序可以打印其中任何一种。

Sample Input

1
103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107

Sample Output

143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127

Answer

#include<iostream>
#include<cstring>
#define B(i,j) (i-1)/3*3+(j-1)/3+1
using namespace std;
int A[10][10];
bool V[3][10][10];
void visit(int i,int j,int k,int f){
    V[0][i][k] = f;
    V[1][j][k] = f;
    V[2][B(i,j)][k] = f;
    A[i][j] = f;
}
pair<int,int> go(int i,int j){
    pair<int,int> n;
    n.first = j==9 ? i+1:i;
    n.second = j==9 ? 1:j+1;
    return n;
}
bool dfs(int i,int j){
    pair<int,int> nx=go(i,j);
    if(i==10) return 1;
    if(A[i][j])
        return dfs(nx.first,nx.second);
    for(int k=1;k<=9;k++){
        bool exist=V[0][i][k]+V[1][j][k]+V[2][B(i,j)][k];
        if(!exist){
            visit(i,j,k,k);
            if( dfs(nx.first,nx.second) )
                return 1;
            else
                visit(i,j,k,0);
        }
    }
    return 0;
}
int main(){
    int n;
    cin>>n;
    while (n--){
        memset(A,0,sizeof(A));
        memset(V,0,sizeof(V));
        for(int i=1;i<=9;i++){
            string str;
            cin>>str;
            for(int j=1;j<=9;j++)
                visit(i,j,str[j-1]-'0',str[j-1]-'0');
        }
        dfs(1,1);
        for(int i=1;i<=9;i++){
            for(int j=1;j<=9;j++)
                cout<<A[i][j];
            cout<<endl;
        }
        cout<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值