数独【dfs】

数独是一种传统益智游戏,你需要把一个9 × 9的数独补充完整,使得图中每行、每列、每个3 × 3的九宫格内数字1~9均恰好出现一次。

请编写一个程序填写数独。

数独.png

输入格式
输入包含多组测试用例。

每个测试用例占一行,包含81个字符,代表数独的81个格内数据(顺序总体由上到下,同行由左到右)。

每个字符都是一个数字(1-9)或一个”.”(表示尚未填充)。

您可以假设输入中的每个谜题都只有一个解决方案。

文件结尾处为包含单词“end”的单行,表示输入结束。

输出格式
每个测试用例,输出一行数据,代表填充完全后的数独。

#include <bits/stdc++.h>
using namespace std;
#define fir(i,a,b) for(int i=a;i<=b;i++)
char str[10][10];
int r[9],c[9],g[9],cnt[512],num[512],tot;
inline int gc(int x, int y)//将二维数组变成一维数组
{
    return ((x/3)*3)+(y/3);
}
inline void pd(int x, int y, int z)//位运算,修改当前位数z,第z位1变为0,0变为1.
{
    r[x]^=1<<z;//横坐标
    c[y]^=1<<z;//纵坐标
    g[gc(x,y)]^=1<<z;//九宫格
}
inline int lowbit(int x)//得到当前可以选择的合法数值.
{
    return x&(-x);
}
inline bool dfs(int now)
{
    if (now==0)
        return 1;
    int temp=10,x,y;
    fir(i,0,8)
    fir(j,0,8)
    {
        if (str[i][j]!='.')
            continue;
        int val=r[i] & c[j] & g[gc(i,j)];//判断这一位是否合法,1为合法,0为不合法
        if (!val)
            return 0;
        if (cnt[val]<temp)//找到当前能填合法数字最小的位置
        {
            temp=cnt[val];
            x=i,y=j;
        }
    }
    
    int val=r[x] & c[y] & g[gc(x, y)];
    for (; val; val-=lowbit(val))
    {
        int z=num[lowbit(val)];
        str[x][y]='1'+z;
        pd(x,y,z);
        if (dfs(now-1))//下一位
            return 1;
        pd(x,y,z);//回溯
        str[x][y]='.';
    }
    return 0;
}
int main()
{
//  freopen("stdin.in","r",stdin);
    for (int i=0; i<1<<9; i++)
        for (int j=i; j; j-=lowbit(j))
            cnt[i]++;
    fir(i,0,8)
    num[1<<i]=i;
    char s[100];
    while (~scanf("%s",s) && s[0]!='e')
    {
        int t=0;
        for(int i=0;i<9;i++)
            for(int j=0;j<9;j++){
                str[i][j]=s[t++];
            }
        fir(i,0,8)
        r[i]=c[i]=g[i]=(1<<9)-1;//初始的是否都是合法的
        
        tot=0;
        fir(i,0,8)
        fir(j,0,8)
        if (str[i][j]!='.')
            pd(i,j,str[i][j]-'1');//这一位已经选择
        
        else
            tot++;//统计需要修改的个数
//      cout<<tot<<endl;
        dfs(tot);
        fir(i,0,8)
        fir(j,0,8)
        s[i*9+j]=str[i][j];//答案输出
        puts(s);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值