ACM:搜索算法专题(4)——跳舞链

题目来源: 
        HihoCoder1317
 

题目描述:
    在N行 M列的棋盘中放置一定数目的棋子,要求从其中选出若干行,使得每一列中恰好有一枚棋子。
    例如,对于下面的棋局,选择1、3、4行,则符合要求:
         


解答:
·精确覆盖问题:

    以上问题可以总结为“精确覆盖问题”。具体定义如下:
        给定一个集合S和它的n个子集s1, s2, ... sn。要求从中选择k个子集满足:
            ① ∪si = S
            ② 对于任意的i≠j si∩sj = ∅
    对于本题目,S即为m列,每一行的棋子摆放局面都是S的一个子集。

·解法:
    对于精确覆盖问题,最直观的解法就是枚举S的所有子集和所有的子集选择方案,寻找符合条件的方案。但是对于有x个元素的集合,子集数目为2^x个,因而选择的子集的策略就有2^(2^x)种,这是一个非常庞大的数字。算法执行效率非常低。
    精确覆盖问题比较好的解法是利用一种称为“跳舞链”的数据结构进行搜索。方法如下:

·数据结构:
    首先定义数据的存储结构,对于精确覆盖问题,一定可以构造一个二维的数表,其中数表的每一行代表一个子集,而每一列则代表全集中的一个元素。对于数表中第i行第j列的元素, 如果第i个子集中包含了全集中的第j个元素,则值为1,否则,值为0。上面例子中的棋局可以用下面的矩阵来表示:
    0 1 0 1
    1 0 1 0
    1 0 0 0
     0 0 1 1
    此时,整个问题就转换为一个稀疏矩阵,这里我们利用双向十字链表存储该矩阵,如下 
 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值