DLX
DLX的一个经典应用。
首先我们需要把这个数独问题转化为一个精确覆盖问题。
根据数独的规则,我们有如下几个限制:
1.每个数字在每一行只能出现一次。限制编号1~81
2.每个数字在每一列只能出现一次。限制编号82~162
3.每个数字在每一个九宫格内只能出现一次。限制编号163~243
4.每一格只能填其中一个数字。限制编号244~364
这些限制就是列。
而数独的全部填法一共有9*81=729种。这些填法就是行。
原问题就转化为一个729*364大小的01矩阵的精确覆盖问题。
加一个优化:每次不选择h的右指针。增加一个数组cnt记录当前列的节点个数,每次选择cnt最小的那个。当删除或恢复时相应地更新cnt。
跑一边DLX就好了。
又臭又长的代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 81*9
#define M 81*4
using namespace std;
struct nd{
nd *u,*d,*l,*r; int x,y;
}c[M+5],a[N*M+5],*h=&c[0],s,*null=&s;
int t,ti,n=N,m=M,cnt[M+5],mp[10][10],ans[10][10],id[N+5][M+5];
bool f[N+5][M+5];
inline void nsrt(int x,int y,int z){
//在(x,y)填入的值为k时的限制
int i=(x-1)*9