问题描述:

给定一个n*m的矩阵,有些位置为1,有些位置为0。如果G[i][j]==1则说明i行可以覆盖j列。

Problem:

1)选定最少的行,使得每列有且仅有一个1.

2)选定最少的行,使得每列至少一个1.

DLX原理:

这类属于NP问题的问题,可以使用搜索解决。但是普通的搜索必超时无疑。因此我们要设法加优化来加快速度。

Dancing Links从数据结构方面对此类搜索进行了优化,通过仅保留矩阵中有用的部分提高了搜索速度。DLX的存储结构采用循环十字链表,在搜索过程中不断将不需要的部分切除,随着迭代深度的增加,矩阵迅速变得稀疏。

甚至一些你想不到的优化,DLX都替你想好了。

对于Problem1)的解:

转化模型:DLX精确覆盖。

DLX 精确覆盖对于当前矩阵的处理是,首先将当前要覆盖的列以及使得能够覆盖到该列的行全部去掉,然后再逐行枚举添加的方法。这是由其“有且仅有一个1”的条件 决定的。枚举某一行r,则设定当前列的解为该行r,那么该行能够覆盖到的列必然全部都可以不必再搜,因此将该行r覆盖到的列全部去掉。又由于去掉的那些列 都相当于已经有了解,那么能够覆盖到那些去掉的列的行也应当全部去掉。

搜完之后记得resume。

对于Problem2)的解:

转换模型:DLX重复覆盖。

DLX 重复覆盖对于当前矩阵的处理是,将当前列去掉,并将选作当前列的解的行能够覆盖到的列全部去掉。因为不需要每列仅由一个1去覆盖,因此不必要把能够覆盖某 一列的所有行全部去掉。因此remove和resume函数的写法将会有所不同(兽家在这里纠结了一会儿= =)。这是与Problem1)的第一个区别。

第二个区别是,由于矩阵密度下降会变慢(因为去掉的少了),因此要加上一个强剪枝。这个 剪枝利用的思想是A*搜索中的估价函数。即,对于当前的递归深度K下的矩阵,估计其最好情况下(即最少还需要多少步)才能出解。也就是,如果将能够覆盖当 前列的所有行全部选中,去掉这些行能够覆盖到的列,将这个操作作为一层深度。重复此操作直到所有列全部出解的深度是多少。如果当前深度加上这个估价函数返 回值,其和已然不能更优(也就是已经超过当前最优解),则直接返回,不必再搜。(其实平时的搜索也会不自觉地使用这个剪枝思想吧)。

关于循环十字链表的构造:

采 用静态链表,不过也不需要内存池。使用L,R,D,U四个数组记录某节点上下左右邻居为谁。使用S记录某列有多少个节点。更新思想同链表。remove之 后会产生一些孤立节点。这看上去不怎么好。但是我们就是要利用这些孤立节点来完成优化。比如删掉节点i,则L[R[i]] = L[i],R[L[i]] = R[i]。这样i这个节点被孤立掉。但是后面resume的时候使用如下语句:L[R[i]] = i,R[L[i]] = i。巧妙地“变废为宝”。

优化:

对于深度K下当前列的选择,采用选择1的个数最少的决策。这是显然的。hdu2295的试验表明,随便选一列将近800MS,而采用这个策略将达到500MS。不过对于当前列的选择,还是要根据具体情况确定。有时候你的代码比别人慢,很可能就是因为这个列的选择。

推荐题目:

Problem1) :

hust1017 裸体DLX精确覆盖。

Problem2):

hdu2295 二分+DLX重复覆盖。

Dancing Links论文中讲到的一题,并以此为基础使另外一些类型的题目转化为此种精确区间覆盖模型用DLX解决。

法描述如下:

深搜:

1、如果矩阵为空,得到结果,返回

2、从矩阵中选择一列,以选取最少元素的列为优化方式

3、删除该列及其覆盖的行

4、对该列的每一行元素:

删除一行及其覆盖的列,

5、进行下一层搜索,如果成功则返回

6、恢复现场,跳至4

7、恢复所选择行

用双向十字链表来维护该矩阵,方便删除与恢复,其中删除操作:

R[L[i]]=L[i];

L[R[i]]=R[i];

恢复操作:

R[L[i]]=i;

L[R[i]]=i;

【转】DLX 精确覆盖 重复覆盖的更多相关文章

  1. dancing link 精确覆盖 重复覆盖 (DLX)

    申明:因为转载的没有给出转载链接,我就把他的链接附上,请尊重原创: http://www.cnblogs.com/-sunshine/p/3358922.html 如果谁知道原创链接 给一下,请尊重原 ...

  2. HDU 3957 Street Fighter(搜索、DLX、重复覆盖+精确覆盖)

    很久以前就看到的一个经典题,一直没做,今天拿来练手.街霸 给n<=25个角色,每个角色有 1 or 2 个版本(可以理解为普通版以及爆发版),每个角色版本可以KO掉若干人. 问最少选多少个角色( ...

  3. DLX 舞蹈链 精确覆盖 与 重复覆盖

    精确覆盖问题:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 还有重复覆盖问题 dancing links 是 一种数据结构,用来优化搜索,不算是一种算法.(双向 ...

  4. HDU 3957 Street Fighter (最小支配集 DLX 重复覆盖+精确覆盖 )

    DLX经典题型,被虐惨了…… 建一个2*N行3*N列的矩阵,行代表选择,列代表约束.前2*N列代表每个人的哪种状态,后N列保证每个人至多选一次. 显然对手可以被战胜多次(重复覆盖),每个角色至多选择一 ...

  5. DLX精确覆盖与重复覆盖模板题

    hihoCoder #1317 : 搜索四·跳舞链 原题地址:http://hihocoder.com/problemset/problem/1317 时间限制:10000ms 单点时限:1000ms ...

  6. SPOJ 1771&&DLX精确覆盖,重复覆盖

    DLX的题,做过这题才算是会吧. 这道题转化成了精确覆盖模型来做,一开始,只是单纯的要覆盖完行列和斜线,WA. 后来醒悟了,不能这样,只要覆盖全部行或列即可.虽然如此,但某些细节地方很关键不能考虑到. ...

  7. zoj 3209.Treasure Map(DLX精确覆盖)

    直接精确覆盖 开始逐行添加超时了,换成了单点添加 #include <iostream> #include <cstring> #include <cstdio> ...

  8. HDU 2295.Radar (DLX重复覆盖)

    2分答案+DLX判断可行 不使用的估计函数的可重复覆盖的搜索树将十分庞大 #include <iostream> #include <cstring> #include < ...

  9. UVA - 1603 Square Destroyer (DLX可重复覆盖+IDA*)

    题目链接 给你一个n*n的由火柴组成的正方形网格,从中预先拿掉一些火柴,问至少还需要拿掉多少火柴才能破坏掉所有的正方形. 看到这道题,我第一反应就是——把每根火柴和它能破坏掉的正方形连边,不就是个裸的 ...

随机推荐

  1. MySQL基础之第7章 索引

    第7章 索引 MySQL中,所有的数据类型都可以被索引,包括普通索引,唯一性索引,全文索引,单列索引,多列索引和空间索引等. 7.1.索引简介 7.1.1.索引的含义和特点 BTREE索引,HASH索 ...

  2. XTUOJ 1246 Heartstone 贪心

    题意:挺好懂得 分析:先计算出如果不能用(减2)操作,至少需要多少个(减3)操作,这个很好计算 然后就是尽量多的去减少(减3)操作,肯定先抹平 余2 和 余1 的,然后就可以了 #include &l ...

  3. bjfu1238 卡特兰数取余

    题目就是指定n,求卡特兰数Ca(n)%m.求卡特兰数有递推公式.通项公式和近似公式三种,因为要取余,所以近似公式直接无法使用,递推公式我简单试了一下,TLE.所以只能从通项公式入手. Ca(n) = ...

  4. UIButton 设置为圆形,并且使用图片(UIImage)当做背景

    -(UIButton *)shareButtonWithIcon:(NSString *)iconName { UIButton *button = [UIButtonbuttonWithType:U ...

  5. xcode 怎么样在发布release版本的时候 不输出log

    我们平时在开发应用的时候,经常会用到 NSLog 来调试我们的程序,而随着项目越来越大,这些用于调试的日志输出就会变得很难管理. 发布正式版的时候一定要屏蔽掉所有后台输出,因为这些输出还是比较消耗系统 ...

  6. CentsOS7 网络自动启动

    虚拟机中安装完成CentOS7后,网络总是需要手工启动才可使用,设置为自动连接的方式如下: cd /etc/sysconfig/network-scripts/ls #找到类似的文件:ifcfg-et ...

  7. Windows7 32位下opencv与python2.66的环境配置

    刚接触Python和OpenCV,对两者都不太了解,因为今后学习会使用到这两种工具,特此学习配置.PS:本帖适用小白. 一. 需要的文件 1. OpenCV 可用OpenCV-2.3.1-win-su ...

  8. 常用抓包指令for wireshark or tcpdump

    1, tshark -ni eth0 -R "tcp.dstport eq 8080" [wireshark 抓指定协议端口数据包] 2, tcpdump  -XvvennSs 0 ...

  9. 注意 sizeof 中不要有复杂运算操作

    http://github.tiankonguse.com/blog/2014/12/05/c-base/ 一个比较有意思的问题 #include<stdio.h> ; int f() { ...

  10. Ubuntu 下安装 Oracle Java

    这只是一篇流水帐,记录如何安装Java. 在Ubuntu 下管理软件很方便,但安装的Java是opensdk.如果在某些条件下,需要安装Sun (Oracle)的Java,则需要自己手工安装. 一般情 ...