看了比我还小,但能力无法比较的陈丹琦 《Dancing Links的应用》
之前看了算法大师 Knuth的论文,感觉很巧妙,但不知道如何实现,然后看了CDQ之后,找了一题最裸的DLX的题开始编。。然后照着她的模板打下去。。。后来怎么交都是错的。特别是她的Recover()那边不知道是写错了还是我不理解。。。改了那里之后就A了。。
#include <iostream>
#include <stdio.h>
using namespace std;
const int M=1000;
const int N=1000;
struct node{
int L,R,D,U,col;
}dia[M*N];
int map[M][N],Size[N];
int n,m;
inline void makegraph()
{
int i,j,now,pre,RP;
//初始化头指针///
for(i=0;i<=n;i++)
{
dia[i].col=i;
dia[i].D=dia[i].U=i;
dia[i].L=i-1;
dia[i].R=i+1;
Size[i] = 0;
}
dia[0].L=n;dia[n].R=0;
now=n+1;
for(i=1;i<=m;i++)
{
RP=pre=now;//RP行指针
for(j=1;j<=n;j++)
if(map[i][j]){
dia[now].col = j;//属于第几列
Size[j] ++;
dia[now].U = dia[j].U;
dia[now].D = j;
dia[dia[j].U].D = now;
dia[j].U = now;
dia[now].L=pre;
dia[now].R=RP;
dia[pre].R = now;
dia[RP].L = now;
pre = now++;
}
}
}
void Cover(int c)
{
dia[dia[c].R].L = dia[c].L;
dia[dia[c].L].R = dia[c].R;
for(int i=dia[c].D;i!=c;i=dia[i].D)
for(int j=dia[i].R;j!=i; j=dia[j].R)
{
dia[dia[j].D].U = dia[j].U;
dia[dia[j].U].D = dia[j].D;
Size[dia[j].col] --;
}
}
void Recover(int c)
{
for(int i=dia[c].U;i!= c;i=dia[i].U)
for(int j=dia[i].L;j!=i;j=dia[j].L)
{
dia[dia[j].U].D = j;
dia[dia[j].D].U = j;
Size[dia[j].col] ++;
}
dia[dia[c].R].L=c;
dia[dia[c].L].R=c;
}
bool Algorithm_X(int depth)
{
int i,j;
if(dia[0].R == 0)
return true;
int mi=0xfffffff,c_pos;
for(i=dia[0].R;i!=0;i=dia[i].R)
if(mi>Size[i]){
mi = Size[i];
c_pos = i;
if(mi == 1) break;
}
if(Size[c_pos] == 0) return false;
Cover(c_pos);
for(i=dia[c_pos].D;i != c_pos; i=dia[i].D)
{
for(j=dia[i].R;j != i; j=dia[j].R)
Cover(dia[j].col);
if(Algorithm_X(depth+1))
return true;
for(j=dia[i].L;j!=i;j=dia[j].L)
Recover(dia[j].col);
}
Recover(c_pos);
return false;
}
int main()
{
int i,j;
while(scanf("%d%d",&m,&n)!= EOF)
{
// memset(Size,0,sizeof(Size));
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
scanf("%d",&map[i][j]);
makegraph();
bool flag = true;
for(i=dia[0].R;i!=0;i=dia[i].R)
if(Size[i]==0){
flag = false;
break;
}
if(flag && Algorithm_X(0))
printf("Yes, I found it/n");
else
printf("It is impossible/n");
}
return 0;
}