Dancing list (两个双向链表构成交叉的图)

#include <iostream>
using namespace std;
const int maxn=2e5;
int L[maxn];//左方向的链表
int R[maxn];//右方向的链表
int U[maxn];//上方向的链表
int D[maxn];//下方向的链表
int C[maxn];//指向列指针头的地址
int S[maxn];//记录列的节点个数
int O[maxn];//result
int head=0;
void remove(const int &c){
    //remove col c and all row i that A[i][c]==1
    L[R[c]]=L[c];
    R[L[c]]=R[c];//双向链表操作
    for(int i=D[c];i!=c;i=D[i]){
        //remove i that A[i][c]==1
        for(int j=R[i];j!=i;j=R[j]){
            U[D[j]]=U[j];
            D[U[j]]=D[j];
            --S[C[j]];//decrease the count of col C[j]
        }
    }
}
void resume(const int &c){
    for(int i=U[c];i!=c;i=U[i]){
        for(int j=L[i];j!=i;j=L[i]){
            ++S[C[j]];
            U[D[j]]=j;
            D[U[j]]=j;
        }
    }
    L[R[c]]=c;
    R[L[c]]=c;
}
bool dfs(const int &k){
    if(R[head]==head){
        return true;
    }
    int s=1e9;
    int c;
    for(int t=R[head];t!=head;t=R[t]){
        if(S[t]<s){
            s=S[t];
            c=t;
        }
    }//选一个列最少为清的出来
    remove(c);
    for(int i=D[c];i!=c;i=D[i]){
        O[k]=i;
        for(int j=R[i];j!=i;j=R[i]){
            remove(C[j]);
        }
        if(dfs(k+1)){
            return true;
        }//继续递归下去
        for(int j=L[i];j!=i;j=L[j]){
            resume(C[j]);
        }//不可行返回
    }
    resume(c);
    return false;

}

总结:1.L[R[c]]=c;
              R[L[c]]=c;

             双向链表的增加操作
           2.U[D[j]]=U[j];
            D[U[j]]=D[j];

            双向链表的删除操作

          3.该段代码解决的是一个1101

                                                 0011

                                                 1100这样一个矩阵选特定的几行样每一列都有一个1

则代码中的dfs是选定列最小的出来来进行选取,加快代码运行的速度,这就是代码做出的优化,这道题是参考

递归求解问题转过来的  http://www.cnblogs.com/steady/archive/2011/03/15/1984791.html

  

猜你喜欢

转载自blog.csdn.net/qq_42193011/article/details/84027178