DLX PKU3740

看了比我还小,但能力无法比较的陈丹琦 《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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值