POJ 2676 Sudoku DFS+回溯+减枝

点击打开链接

题意:把一个9行9列的网格,

再细分为9个3*3的子网格,要求每行、每列、每个子网格内都只能使用一次1~9中的一个数字
,即每行、每列、每个子网格内都不允许出现相同的数字。

思路:
用三个数组进行标记每行、每列、每个子网格已用的数字,用于剪枝
bool row[10][10];    //row[i][x]  标记在第i行中数字x是否出现了
bool col[10][10];    //col[j][y]  标记在第j列中数字y是否出现了
bool grid[10][10];   //grid[k][z] 标记在第k个3*3子格中数字z是否出现了

DFS试探,下一层匹配失败则回溯


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#define PI acos(-1)
#define eps 0.00000001
using namespace std;
int a[11][11];
char s[11];
int Lvis[11][11],Rvis[11][11],vis[11][11];          
int flag=0;
int DFS(int x,int y)
{
    if(x==10)
        return 1;
    if(!a[x][y])
    {
        int k=(x-1)/3*3+(y-1)/3+1;
        for(int i=1; i<=9; i++)
        {
            if(!Rvis[x][i]&&!Lvis[y][i]&&!vis[k][i])          
            {
                a[x][y]=i;
                Rvis[x][i]=Lvis[y][i]=vis[k][i]=1;
                if(y==9)                                        ///遍历下一层
                    flag=DFS(x+1,1);
                else
                    flag=DFS(x,y+1);
                if(flag==0)    ///flag==0  表示下一层匹配失败     需要回溯
                {                     ///说明上面的赋值有问题
                     a[x][y]=0;
                     Rvis[x][i]=Lvis[y][i]=vis[k][i]=0;
                }
            }
        }
    }
    else
    {
        if(y==9)
            flag=DFS(x+1,1);
        else
            flag=DFS(x,y+1);
        if(flag==0)           ///flag==0  表示下一层匹配失败     需要回溯
                               ///说明上面的赋值有问题
        return 0;
        else
             return 1;
    }
    if(!a[x][y])                   ///表示匹配失败了
    return 0;
    else
    return 1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        flag=0;
        memset(vis,0,sizeof(vis));
        memset(Lvis,0,sizeof(Lvis));
        memset(Rvis,0,sizeof(Rvis));
        for(int i=1; i<=9; i++)
        {
            scanf("%s",s);
            for(int j=1; j<=9; j++)
            {
                a[i][j]=s[j-1]-'0';
                if(a[i][j])
                {
                    int k=(i-1)/3*3+(j-1)/3+1;
                    Rvis[i][a[i][j]]=1;
                    Lvis[j][a[i][j]]=1;
                    vis[k][a[i][j]]=1;        
                }
            }
        }
        DFS(1,1);
        for(int i=1; i<=9; i++)
        {
            for(int j=1; j<=9; j++)
            {
                printf("%d",a[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值