3740

来源:互联网 发布:软件著作权登记日期 编辑:程序博客网 时间:2024/06/06 03:53

精确覆盖(dancing link)的板子题。

参考了下面的博客:

这个博客虽然不是用c++写的代码,但讲的十分详细,有助于理解。http://www.cnblogs.com/grenet/p/3145800.html

又短又漂亮的c++代码,值得一膜:http://blog.csdn.net/xianxingwuguan1/article/details/18994601

下面是我的代码(实际上长得和上面那个博客里的一膜一样


#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>using namespace std;#define rep(i,j,k) for(i=j;i<=k;++i)#define per(i,j,k) for(i=j;i>=k;--i)#define ll long long#define db double#define mkp(x,y) make_pair(x,y)#define pii pair<int,int>#define X first#define Y secondconst int N=20,M=305,NM=7000;int n,m;struct DLX{int L[NM],R[NM],U[NM],D[NM]/*,ro[NM]*/,co[NM],H[N],S[M]/*,cnt*/,sz/*,ans[N]*/;//H为行首,S为每列元素个数 void reset(){int i;rep(i,0,m)S[i]=0,L[i]=i-1,R[i]=i+1,U[i]=D[i]=i;L[0]=m,R[m]=0,sz=m+1;memset(H,-1,sizeof H);}void ins(int x,int y){++S[co[sz]=y]/*,ro[sz]=x*/;//确定所在行、列 U[D[sz]=D[y]]=sz;U[D[y]=sz]=y;//将sz插入y和D[y]中if(H[x]<0)H[x]=L[sz]=R[sz]=sz;else{L[R[sz]=R[H[x]]]=sz;R[L[sz]=H[x]]=sz;}//将sz插入H[x]和R[H[x]]中++sz; }void del(int c){R[L[R[c]]=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])D[U[D[j]]=U[j]]=D[j],--S[co[j]];}void add(int c){R[L[c]]=L[R[c]]=c;int i,j;for(i=U[c];i!=c;i=U[i])for(j=L[i];j!=i;j=L[j])++S[co[U[D[j]]=D[U[j]]=j]];}bool DFS(/*int k*/){if(!R[0]){/*cnt=k;*/return 1;} int c,i,j;for(i=c=R[0];i;i=R[i])if(S[c]>S[i])c=i;//找出元素最多的一列 del(c);for(i=D[c];i!=c;i=D[i]){for(j=R[i];j!=i;j=R[j])del(co[j]);//ans[k]=ro[i]; if(DFS(/*k+1*/))return 1;for(j=L[i];j!=i;j=L[j])add(co[j]);}add(c);return 0;}}dlx;int main(){int i,j,x;while(~scanf("%d%d",&n,&m)){dlx.reset();rep(i,1,n)rep(j,1,m){scanf("%d",&x);if(x)dlx.ins(i,j);}puts(dlx.DFS(/*0*/)?"Yes, I found it":"It is impossible");}return 0;}

原创粉丝点击