代码
struct DLX {int n,id;int L[maxn],R[maxn],U[maxn],D[maxn];int C[maxn],S[maxn],loc[maxn][2];void init(int nn=0) //传列长 {n=nn;for(int i=0;i<=n;i++) U[i]=D[i]=i,L[i]=i-1,R[i]=i+1;L[0]=n; R[n]=0;id=n;memset(S,0,sizeof(S));}void AddRow(int x,int col,int A[]) //传入参数是行标号,列长,列数组 {bool has=false;int first=id+1;for(int y=1;y<=col;y++){if(A[y]==0) continue;has=true;++id;L[id]=id-1; R[id]=id+1;D[id]=y; U[id]=U[y];D[U[y]]=id; U[y]=id;loc[id][0]=x,loc[id][1]=y;C[id]=y; S[y]++;}if(!has) return;R[id]=first; L[first]=id;}void Remove(int Size){for(int j=D[Size];j!=Size;j=D[j])//将左右两边连接L[R[j]]=L[j],R[L[j]]=R[j];}void Resume(int Size){for(int j=U[Size];j!=Size;j=U[j])//恢复L[R[j]]=R[L[j]]=j;}bool vis[ms];//标记行是否访问过int h() //启发式函数 {int ret=0;int i,j,k;memset(vis,0,sizeof(vis));for(i=R[0];i;i=R[i]){if(vis[i]) continue;ret++;for(j=D[i];j!=i;j=D[j]) //所有关联的标记了for(k=R[j];k!=j;k=R[k]) vis[C[k]]=1;}return ret;}void dfs(int step){if(step+h()>=ans) return;if(R[0]==0){ ans=min(ans,step); return; }int Min=INF,c=-1;for(int i=R[0];i;i=R[i]) if(Min>S[i]){ Min=S[i]; c=i; }for(int i=D[c];i!=c;i=D[i]){Remove(i);for(int j=R[i];j!=i;j=R[j]) Remove(j);dfs(step+1);for(int j=L[i];j!=i;j=L[j]) Resume(j);Resume(i);}return;} }dlx;