hihocoder1321 搜索五·数独

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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值