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

如果谁知道原创链接 给一下,请尊重原创;

问题描述:

给定一个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;

最新文章

  1. Atitit 在线支付系统功能设计原理与解决方案 与目录
  2. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.7,优化视频聊天、控制更多相关细节
  3. JavaScript使用DeviceOne开发实战(四)仿优酷视频应用
  4. Tomcat:云环境下的Tomcat设计思路——Tomcat的多实例安装
  5. $(document).ready(){}、$(fucntion(){})、(function(){})(jQuery)onload()的区别
  6. Scala 深入浅出实战经典 第47讲:Scala多重界定代码实战及其在Spark中的应用
  7. 基于visual Studio2013解决算法导论之024双向链表实现
  8. [转载]如何快速下载、安装和配置chromedriver ?
  9. POJ 3104 Drying (经典)【二分答案】
  10. 089实战 Nginx的安装
  11. tp配置
  12. 通过修改源码,免插件实现wordpress去除链接中的category
  13. 让SQL SERVER自动清理掉处于SLEEPING状态超过30分钟的进程(转)
  14. JavaWeb学习总结(四):Servlet开发(二)
  15. Hadamard product
  16. 排查Hive报错:org.apache.hadoop.hive.serde2.SerDeException: java.io.IOException: Start of Array expected
  17. 20.并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解
  18. submit提交表单
  19. Eden的退役记
  20. django博客项目9

热门文章

  1. Silverlight 离线安装包
  2. lfu-cache(需要O(1),所以挺难的)
  3. Git 的使用Git Bash和Git GUI
  4. Spring核心(ioc控制反转)
  5. DataGridView.DataSource= list(Of T)
  6. hihocoder 1032 manachar 求回文串O(n)
  7. 计算机的一些经典书籍CS经典书单
  8. logstash+es+kibana+redis搭建
  9. swift学习_xcode6搭建
  10. shell tr命令的使用