近日闲来无事,通宵写写代码,啃了下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]==-1) continue;
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]==-1) continue;
++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;
}