Sudoku数独(dfs+状态压缩)

Sudoku数独

题目地址:https://ac.nowcoder.com/acm/problem/51013

题意

编程实现9x9数独

输入

将9x9的数独以字符串的形式输入,81个字符,’.'表示需要补齐的数字。
以‘end’作为结束符

输出

同输入的形式,81个数字字符。
Sudoku数独(dfs+状态压缩)_第1张图片

题解

状态压缩:因为数独需要保证,每一行,每一列,每一宫的数字互不相同,那么就可以以二进制的形式表示这三种情况,比如:
举某个数独的一部分,第一行,第一列,第一个宫:
7 1 ? 4 ? 9 ? 5 8
3 ? 5
4 ? 8

9
?
1
?
6
8

第一行表示为000100110:即若有这个数字则标记为0,没有则标记为1,为了存储方便,化为十进制保存,即38
第一列表示为000010010
第一宫表示为100100010

因此只需要对这三种情况,“与”运算即可得到,都为1的位置,得到这个十进制数,然后通过lowbit得到依次得到,每一个1代表的数字,因此只需要记录所有的空值,然后通过位运算对所有空值dfs就可以得到最后答案。
因为数据保证有解,只需要输出满足数独的一种解即可,所以最终满足条件填满即可return,因此,采取先填哪些可能性少的空值,能避免过多次数的回溯,需要加上这一优化才能过这道题。

代码

#include
using namespace std;
#define ll long long
#define N 12
#define maxm 100
#define INF 2147483640
#define IOS ios::sync_with_stdio(false)
#define mod 10007

struct node{
    int x,y;
};

int ff[N][N];
int R[N],C[N],G[N/3][N/3]; //状态压缩,1表示空值
vectorV;  //记录所有空值的坐标

int mp[1<>1;
    }
    return cnt;
}

bool dfs(int cur)
{
    if(cur==V.size())
        return true;

    int minv=12,id=0;
    for(int i=0;i>str;
        if(str[0]=='e')
            break;

        init();
        for(int i=0; i<9; i++)
            for(int j=0; j<9; j++)
            {
                if(str[i*9+j]=='.')
                {
                    ff[i][j]=0;
                    V.push_back(node{i,j});
                }
                else
                {
                    ff[i][j]=str[i*9+j]-48;
                    int t=ff[i][j];
                    R[i]-=(1<

你可能感兴趣的:(dfs,状态压缩)