【算法】 poj3740Easy Finding-dancing link

版权声明:欢迎转载(请附带原链接)ヾ(๑╹◡╹)ノ" https://blog.csdn.net/corsica6/article/details/82917559

传送门:poj3740


存模板用。
讲解:跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题

代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
#define RI register
#define gc getchar()
#define si isdigit(cp)
using namespace std;
const int N=7000;

int cnt,cur,dir[500],stk[N],top;
int m,n,up[N],dn[N],lf[N],rt[N];
int r[N],c[N];

char cp;
inline int rd()
{
	cp=gc;int x=0;
	for(;!si;cp=gc);
	for(;si;cp=gc) x=x*10+(cp^48);
	return x;
}

inline void init()
{
	RI int i,j,x,pre;
	cnt=n;top=0;
	lf[0]=max(1,n-1);rt[0]=1;
	for(i=1;i<=n;++i){
		dir[i]=up[i]=dn[i]=c[i]=i;
		lf[i]=i-1;rt[i]=i+1;
	}rt[n]=0;
	for(i=1;i<=m;++i){
		for(pre=0,j=1;j<=n;++j) 
		  if((rd())){
		  	 cnt++;r[cnt]=i;c[cnt]=j;
		  	 up[cnt]=dir[j];dn[dir[j]]=cnt;dn[cnt]=j;dir[j]=cnt;
		  	 if(!pre) lf[cnt]=rt[cnt]=cnt;
		  	 else{ lf[cnt]=pre;rt[cnt]=rt[pre];rt[pre]=cnt;}
		  	 pre=cnt;
		  }
	}
}

inline void del(int c)
{
	RI int i,x;lf[rt[c]]=lf[c];rt[lf[c]]=rt[c];
	for(x=dn[c];x!=c;x=dn[x])
		for(i=rt[x];i!=x;i=rt[i])
		 dn[up[i]]=dn[i],up[dn[i]]=up[i];
}

inline void recol(int c)
{
	RI int i,x;rt[lf[c]]=c;lf[rt[c]]=c;
	for(x=dn[c];x!=c;x=dn[x])
	 for(i=rt[x];i!=x;i=rt[i])
	  dn[up[i]]=up[dn[i]]=i;
}

bool dfs()
{
	if(!rt[0]) return true;
	RI int i,j,id=rt[0],x;
	del(id);
    for(x=dn[id];x!=id;x=dn[x]){
    	for(i=rt[x];i!=x;i=rt[i]) del(c[i]);
    	if(dfs()) return true;
    	for(i=rt[x];i!=x;i=rt[i]) recol(c[i]);
    }
    recol(id);
    return false;
}

int main(){
	while(scanf("%d%d",&m,&n)!=EOF){
		init();
	    puts(dfs()?"Yes, I found it":"It is impossible");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/82917559