POJ3740 Easy Finding 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目
精确覆盖问题模板题
算法
DLX算法
代码
#include <cstring> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> using namespace std; const int N=16+5,M=300+5; struct X{ int L,R,U,D,Col,Row; }p[N*M]; int n,m; int g[N][M],C[M],cnt=0; bool flag=0; void Delete(int k){ p[p[k].R].L=p[k].L; p[p[k].L].R=p[k].R; for (int i=p[k].D;i!=k;i=p[i].D) for (int j=p[i].R;j!=i;j=p[j].R){ C[p[j].Col]--; p[p[j].U].D=p[j].D; p[p[j].D].U=p[j].U; } } void Reset(int k){ p[p[k].L].R=k; p[p[k].R].L=k; for (int i=p[k].U;i!=k;i=p[i].U) for (int j=p[i].L;j!=i;j=p[j].L){ C[p[j].Col]++; p[p[j].U].D=j; p[p[j].D].U=j; } } bool DLX(){ if (p[0].R==0) return true; int k=p[0].R; for (int i=p[k].R;i!=0;i=p[i].R) if (C[i]<C[k]) k=i; Delete(k); for (int i=p[k].D;i!=k;i=p[i].D){ for (int j=p[i].R;j!=i;j=p[j].R) Delete(p[j].Col); if (DLX()) return true; for (int j=p[i].L;j!=i;j=p[j].L) Reset(p[j].Col); } Reset(k); return false; } int main(){ while (~scanf("%d%d",&n,&m)){ for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&g[i][j]); memset(p,0,sizeof p); memset(C,0,sizeof C); for (int i=0;i<=m;i++) p[i].L=i-1,p[i].R=i+1,p[i].U=p[i].D=i; p[0].L=m,p[m].R=0,cnt=m; for (int i=1;i<=n;i++){ int first=cnt+1; for (int j=1;j<=m;j++) if (g[i][j]){ cnt++; p[cnt].L=cnt-1; p[cnt].R=cnt+1; p[cnt].D=j; p[p[j].U].D=cnt; p[cnt].U=p[j].U; p[j].U=cnt; C[p[cnt].Col=j]++; p[cnt].Row=i; } if (cnt>=first) p[first].L=cnt,p[cnt].R=first; } if (DLX()) puts("Yes, I found it"); else puts("It is impossible"); } return 0; }