POJ 2676 Sudoku (数独求解器 DFS)

题目链接

POJ2676

题目大意

输入n个数独,空格用0表示,填数独(符合的一种方案即可)。

分析

类似于八皇后的简单搜索题,用DFS回溯法求解。
将空格的位置都记录下来,1个1个填下去,填不下去就清空换其他数字。
关键进行可行性剪枝:
row[i][j]:记录第i行数字j是否可填
column[i][j]:记录第i列数字j是否可填
block[i][j]:记录第i个九宫格数字j是否可填

代码

#include <iostream>
#include <cstring>
using namespace std;
bool row[10][10],column[10][10],block[10][10],flag;
int s[10][10],cnt;
struct
{
    int x,y;
}p[730]; //记录空格的坐标
int num(int x,int y) //返回(x,y)属于第几个九宫格
{
    if (1<=x&&x<=3&&1<=y&&y<=3) return 1;
    if (1<=x&&x<=3&&4<=y&&y<=6) return 2;
    if (1<=x&&x<=3&&7<=y&&y<=9) return 3;
    if (4<=x&&x<=6&&1<=y&&y<=3) return 4;
    if (4<=x&&x<=6&&4<=y&&y<=6) return 5;
    if (4<=x&&x<=6&&7<=y&&y<=9) return 6;
    if (7<=x&&x<=9&&1<=y&&y<=3) return 7;
    if (7<=x&&x<=9&&4<=y&&y<=6) return 8;
    if (7<=x&&x<=9&&7<=y&&y<=9) return 9;
}
void Init()
{
    cnt=0;
    flag=false;
    memset(row,true,sizeof(row));
    memset(column,true,sizeof(column));
    memset(block,true,sizeof(block));
}
void Print()
{
    for (int i=1;i<=9;i++)
    {
        for (int j=1;j<=9;j++)
            cout<<s[i][j];
        cout<<endl;
    }
}
void dfs(int t)
{
    if (t==cnt+1) //当所有空格都填完了
    {
        flag=true;//找到1个答案就不用搜索了
        Print();
    }
    if (flag) return;
    int x,y;
    x=p[t].x;y=p[t].y;
    for (int i=1;i<=9;i++)
        if (row[x][i]&&column[y][i]&&block[num(x,y)][i])
        {
            s[x][y]=i;
            row[x][i]=column[y][i]=block[num(x,y)][i]=false;
            dfs(t+1);
            if (flag) return;
            s[x][y]=0;
            row[x][i]=column[y][i]=block[num(x,y)][i]=true;//回溯,清空标记
        }
    return;
}
int main()
{
    int test,i,j;
    char ch;
    cin>>test;
    while (test--)
    {
        Init();
        for (i=1;i<=9;i++)
            for (j=1;j<=9;j++)
            {
                cin>>ch;
                s[i][j]=ch-'0';
                if (!s[i][j])
                {
                    p[++cnt].x=i;
                    p[cnt].y=j;
                }
                else
                {
                    row[i][s[i][j]]=false;
                    column[j][s[i][j]]=false;
                    block[num(i,j)][s[i][j]]=false;
                }
            }
        dfs(1);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值