数独转Dacing-Links优化的精确覆盖问题

推荐博客传送门.

精确覆盖问题:

有一个n行m列的01矩阵。

你要选一些行,使得每一列都有且仅有一个1。

数独转精确覆盖问题:

首先数独有四个限制:

1.每个格子能填也只能填一个数字。
2.每一行要填满九个数字。
3.每一列要填满九个数字。
4.每一宫要填满九个数字。

格子有9*9=81个,行列宫分别也有9个,每个要9个数字,所以一共有9*9*4列。

行的话也很简单。

一共9*9个格子,每个有9种填法,一共有9*9*9行。

*如果一个格子上已经有数字了,只往那个数字对应的一行加1。

暴力解决精确覆盖问题:

显然就是枚举行,找到行上有1的位置,找到有1的位置对应列,找到列上有1的位置,删掉整行。

然后变成子精确覆盖问题。

dancing-links优化精确覆盖问题:

发现上面这个递归过程贼难写,且常会用到不用的点多次。

dancing-links精确的说是数据结构,是个双向十字循环链表。

如图所示(盗图狗路过):
这里写图片描述

递归的第一步是判断head的右指针是否指向自己,如果是,就出解了。

不然找到head的右指针指向的点的下指针指向的点。

然后用链表的方法去删除。

还原也是用链表的方法去还原。

注意删除时如果是从左到右,还原一定要从右到左,不要想当然以为没有关系。

效率:

dancing-links除了优化一下递归的缓存, 在空间和时间上没有任何优势。

所以我们需要加—优—化。

感性认识(前辈经验)告诉我们,每次找1的个数较少的行会快一点。

事实上它不是快了一点,在有解的时候你是无法想象这个优化的作用之大的。

还有一个优化我们搜出来是一个行的集合,它是无序的,

针对这个,可以把一开始格子就有数字的格子提前搞掉,这样减少了矩阵规模。

裸题:
JZOJ 4373. 【GDOI2016模拟】数独

16*16的数独,300ms+

Code:

#include<cstdio>
#include<cstring>
#define f
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SAT 问题即命题逻辑公式的可满足性问题(satisfiability problem),是计算机科学与人工智能基本问题,是一个典型的 NP 完全问题,可广泛应用于许多实际问题如硬件设计、安全协议验证等,具有重要理论意义与应用价值。本设计要求基于 DPLL 算法实现一个完备 SAT 求解器,对输入的 CNF 范式算例文件,解析并建立其内部表示;精心设计问题中变元、文字、子句、公式等有效的物理存储结构以及一定的分支变元处理策略,使求解器具有优化的执行性能;对一定规模的算例能有效求解,输出与文件保存求解结果,统计求解时间。 要求具有如下功能: 输入输出功能:包括程序执行参数的输入,SAT 算例 cnf 文件的读取,执行结果的输出与文件保存等。(15%) 公式解析与验证:读取 cnf 算例文件,解析文件,基于一定的物理结构,建立公式的内部表示;并实现对解析正确性的验证功能,即遍历内部结构逐行输出与显示每个子句,与输入算例对比可人工判断解析功能的正确性。数据结构的设计可参考文献[1-3]。(15%) DPLL过程:基于DPLL算法框架,实现SAT算例的求解。(35%) 时间性能的测量:基于相应的时间处理函数(参考 time.h),记录 DPLL 过程执行时间(以毫秒为单位),并作为输出信息的一部分。(5%) 程序优化:对基本 DPLL 的实现进行存储结构、分支变元选取策略[1-3]等某一方面进行优化设计与实现,提供较明确的性能优化率结果。优化率的计算公式为:[(t-to)/t]*100%,其中 t 为未对 DPLL 优化时求解基准算例的执行时间,to 则为优化 DPLL 实现时求解同一算例的执行时间。(15%) SAT应用:将二进制数独游戏[5,6]问题转化为SAT问题[6],并集成到上面的求解器进行问题求解,游戏可玩,具有一定的/简单的交互性。应用问题归约为SAT问题的具体方法可参考文献[3]与[6-9]。(15%)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值