Dancing Links

    近日闲来无事,通宵写写代码,啃了下Knuth大师的论文,实在惊讶于Dancing Links的优美,于是不免心血来潮,用面向对象的方法写了近400行,结果发现很多安全隐患,遂改了下用面向过程的方式,在HUST上搞了那道1017,还不错232ms,把主要模版代码发下,希望大家指正。

#include <iostream>
using namespace std;

const int MAXN=1010;
const int MAXLEN=MAXN*100+MAXN;
int L[MAXLEN];
int R[MAXLEN];
int D[MAXLEN];
int U[MAXLEN];
int nRow[MAXLEN];
int nCol[MAXLEN];

int Col[MAXN]; //判定列集是否已插入
int Row[MAXN]; //判定行集是否已插入
int RC[MAXN][MAXN]; //判定元素是否已插入
int RS[MAXN],CS[MAXN]; //行长与列长
int eid; //内存标识
int head;
int Cn;
int N,M;
int ans[MAXN];
int alen;

//DLX算法 进行精确覆盖 判定前请先判断是否各列中都有1存在
//对于行列唯一的情况 可以考虑将RC数组取消以加速
inline void init()
{
    memset(Row,
-1,sizeof(Row));
    memset(Col,
-1,sizeof(Col));
    memset(RC,
-1,sizeof(RC));
    memset(nCol,
-1,sizeof(nCol));
    memset(nRow,
-1,sizeof(nRow));
    head
=0;
    L[head]
=R[head]=D[head]=U[head]=head;
    eid
=1;
    Cn
=0;
}


//插入行

inline 
void insRow(int r)
{
    
    U[D[head]]
=eid;
    U[eid]
=head;
    D[eid]
=D[head];
    D[head]
=eid;
    
    L[eid]
=R[eid]=eid;
    
    RS[r]
=1;
    Row[r]
=eid++;
}


//插入列

inline 
void insColumn(int c)
{
    L[R[head]]
=eid;
    L[eid]
=head;
    R[eid]
=R[head];
    R[head]
=eid;
    
    U[eid]
=D[eid]=eid;
    
    CS[c]
=1;
    Col[c]
=eid++;
}


//插入元素

inline 
void insElement(int r,int c)
{
    
int rid=Row[r];
    
int cid=Col[c];
    
    L[R[rid]]
=eid;
    L[eid]
=rid;
    R[eid]
=R[rid];
    R[rid]
=eid;
    
    
    U[D[cid]]
=eid;
    U[eid]
=cid;
    D[eid]
=D[cid];
    D[cid]
=eid;
    
    
    nRow[eid]
=r;
    nCol[eid]
=c;
    
    
++CS[c];
    
++RS[r];

    RC[r][c]
=eid;
    
++eid;
}


//插入操作

inline 
void insert(int r, int c)
{

    
if (Col[c]==-1)
    
{
        
++Cn;
        insColumn(c);
    }


    
if(Row[r]==-1)
    
{
        insRow(r);
    }


    
if(RC[r][c]==-1)
    
{
        insElement(r,c);
    }


}


//删除列(使用cid)

inline 
void RemoveCol(int c)
{
    
//c=Col[c];

    L[R[c]]
=L[c];
    R[L[c]]
=R[c];

    
int i,j;

    
for (i=D[c];i!=c;i=D[i])
    
{
        
for (j=R[i];j!=i;j=R[j])
        
{
        
if(nCol[j]==-1continue;
            U[D[j]]
=U[j];
            D[U[j]]
=D[j];
            
--CS[nCol[j]];
        }

    }


}


//恢复列(使用cid)

inline 
void ResumeCol(int c)
{
    
//c=Col[c];

    
int i,j;

    
for (i=U[c];i!=c;i=U[i]) 
    
{
        
for (j=L[i];j!=i;j=L[j]) 
        
{
        
if(nCol[j]==-1continue;
            
++CS[nCol[j]];
            U[D[j]]
=j;
            D[U[j]]
=j;
        }

    }


    L[R[c]]
=c;
    R[L[c]]
=c;
}


//遍历

inline 
void debug()
{
    
    
int i,j;
    
for (i=D[head];i!=head;i=D[i])
    
{
        
for (j=R[i];j!=i;j=R[j])
        
{
            printf(
"%d,%d ",nRow[j],nCol[j]);
        }

        puts(
"");
    }

}


//精确覆盖

inline 
bool dfs(int k)
{

    
if (R[head]==head)
    
{
        alen
=k;
        
return true;
    }


    
int i,j;

    
int s=INT_MAX;
    
int c;

    
for (i=R[head];i!=head;i=R[i])
    
{
         if(nCol[D[i]]==-1) {c=i;continue;}

        
if (CS[nCol[D[i]]]<=s)
        
{
            s
=CS[nCol[D[i]]];
            c
=i;
        }

    }


    RemoveCol(c);

    
for (i=D[c];i!=c;i=D[i])
    
{
        ans[k]
=nRow[i];
        
for (j=R[i];j!=i;j=R[j])
        
{
            
if (nCol[j]==-1)
            
{
                
continue;
            }

            RemoveCol(Col[nCol[j]]);
        }

        
        
if(dfs(k+1))
        
{
            
return true;
        }


        
for (j=L[i];j!=i;j=L[j])
        
{
            
if (nCol[j]==-1)
            
{
                
continue;
            }

            ResumeCol(Col[nCol[j]]);
        }

    }


    ResumeCol(c);    
    
return false;
}
posted @ 2009-07-29 20:51  Hdu-Lost  阅读(1278)  评论(3编辑  收藏  举报