Dancing Links 详解

Dancing Links 详解

1.初始化部分:建立一行头节点

第0行建立好一排空的头节点,完善好十字链表的各项信息。
e6f8bd290e7f571e4e3904ebd95fda8.jpg

void init(){
    for(int i=0;i<=m;++i){
        l[i]=i-1,r[i]=i+1;
        u[i]=d[i]=i;
    }
    l[0]=m,r[m]=0;
    idx=m+1;
}

2.插入元素

每次在第0行下面插入,虽然直观上行的顺序打乱,实际上是翻转了一下,不影响拓扑结构

void add(int &hh,int &tt,int x,int y){
    row[idx]=x,col[idx]=y,s[y]++;
    u[idx]=y,d[idx]=d[y],u[d[y]]=idx,d[y]=idx;
    l[idx]=hh,r[hh]=idx,r[idx]=tt,l[tt]=idx;
    tt=idx++;
}

3.删除某一列 & 恢复某一列

(1) 在头结点中删除该列 (只删除右指针,左指针复原的时候要用,一般索引都是用右指针,所以删除右指针意味着逻辑上已经删除了,不会再被遍历到)
(2) 删除当前列意味着当前列已经被覆盖,因此凡是有1在这一列的行都不能被选择,可以全部删去。因此删去当前列所有1所在的行
(3) 恢复完全对称写即可,每次遍历使用d[]和r[]两个指针,因此恢复使用另外两个
5cb80766e6cf450f8abf03cbea9c7ea.jpg

void remove(int p){ //删除第p列
    r[l[p]]=r[p],l[r[p]]=l[p];
    for(int i=d[p];i!=p;i=d[i])
        for(int j=r[i];j!=i;j=r[j]){
            s[col[j]] --;
            u[d[j]]=u[j],d[u[j]]=d[j];
        }
}

void resume(int p){ //恢复第p列
    for(int i=u[p];i!=p;i=u[i])
        for(int j=l[i];j!=i;j=l[j]){
            s[col[j]] ++;
            u[d[j]]=j,d[u[j]]=j;
        }
    l[r[p]]=p,r[l[p]]=p;
}

4.深搜DFS+剪枝

剪枝有两种
(1) 每次枚举1最少的列
(2) remove中用到的,当前列能且只能被覆盖1次
借用OIwiki的一张图,这个剪枝效果还是十分明显的
屏幕截图 2022-02-26 131629.jpg
屏幕截图 2022-02-26 131643.jpg
屏幕截图 2022-02-26 131650.jpg [1]

bool dfs(){
    if(!r[0]) return true;
    int p=r[0];
    for(int i=r[0];i;i=r[i])
        if(s[i] < s[p]) p=i;
    remove(p);
    for(int i=d[p];i!=p;i=d[i]){
        ans[++ top]=row[i];
        for(int j=r[i];j!=i;j=r[j]) remove(col[j]);
        if(dfs()) return true;
        for(int j=l[i];j!=i;j=l[j]) resume(col[j]);
        top --;
    }
    resume(p);
    return false;
}

[1] 引用自 OI wiki https://oi-wiki.org/search/dlx/#__comments

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值