精确覆盖DLX算法模板另一种写法

代码

struct DLX
{
    int n,id;
    int L[maxn],R[maxn],U[maxn],D[maxn];
    int C[maxn],S[maxn],loc[maxn][2];
    int H[ms];
    void init(int nn=0) //传列长
    {
        n=nn;
        for(int i=0;i<=n;i++) U[i]=D[i]=i,L[i]=i-1,R[i]=i+1;
        L[0]=n; R[n]=0;
        id=n;
        memset(S,0,sizeof(S));
        memset(H,-1,sizeof(H));
    }
    void Link(int x,int y)
    {
        ++id;
        D[id]=y; U[id]=U[y];
        D[U[y]]=id; U[y]=id;
        loc[id][0]=x,loc[id][1]=y;
        C[id]=y; S[y]++;
        if(H[x]==-1) H[x]=L[id]=R[id]=id;
        else
        {
            int a=H[x];
            int b=R[a];
            L[id]=a; R[a]=id;
            R[id]=b; L[b]=id;
            H[x]=id;
        }
    }
    void Remove(int Size)
    {
        for(int j=D[Size];j!=Size;j=D[j])//将左右两边连接
            L[R[j]]=L[j],R[L[j]]=R[j];
    }
    void Resume(int Size)
    {
        for(int j=U[Size];j!=Size;j=U[j])//恢复
            L[R[j]]=R[L[j]]=j;
    }
    bool vis[ms];//标记行是否访问过
    int h() //启发式函数
    {
        int ret=0;
        int i,j,k;
        memset(vis,0,sizeof(vis));
        for(i=R[0];i;i=R[i])
        {
           if(vis[i]) continue;
           ret++;
           for(j=D[i];j!=i;j=D[j]) //所有关联的标记了
               for(k=R[j];k!=j;k=R[k]) vis[C[k]]=1;
        }
        return ret;
    }
    void dfs(int step)
    {
        if(step+h()>=ans) return;
        if(R[0]==0){ ans=min(ans,step); return; }
        int Min=INF,c=-1;
        for(int i=R[0];i;i=R[i]) if(Min>S[i]){ Min=S[i]; c=i; }
        for(int i=D[c];i!=c;i=D[i])
        {
            Remove(i);
            for(int j=R[i];j!=i;j=R[j]) Remove(j);
            dfs(step+1);
            for(int j=L[i];j!=i;j=L[j]) Resume(j);
            Resume(i);
        }
        return;
    }
}dlx;
View Code
原文地址:https://www.cnblogs.com/wust-ouyangli/p/5747248.html