标签:
DancingLinksX重复覆盖的题目
题目意思&……
做法
龙的一次攻击作为行
格点作为列
龙对应的一次攻击能打到的位置为1
求重复覆盖的最小次数
这里特别的把没有生物的格点直接去掉了
这样就少了很多列
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; const int MN=20*20; const int MM=20*20; const int MNN=MN*MM+MM; //最大点数 struct DLX { int n,m,si;//n行数m列数si目前有的节点数 //十字链表组成部分 int U[MNN],D[MNN],L[MNN],R[MNN],Row[MNN],Col[MNN]; //第i个结点的U向上指针D下L左R右,所在位置Row行Col列 int H[MN],S[MM]; //记录行的选择情况和列的覆盖情况 int ansd,ans[MN]; void init(int _n,int _m) //初始化空表 { n=_n; m=_m; for(int i=0;i<=m;i++) //初始化第一横行(表头) { S[i]=0; U[i]=D[i]=i; //目前纵向的链是空的 L[i]=i-1; R[i]=i+1; //横向的连起来 } R[m]=0;L[0]=m; si=m; //目前用了前0~m个结点 for(int i=1;i<=n;i++) H[i]=-1; } void link(int r,int c) //插入点(r,c) { ++S[Col[++si]=c]; //si++;Col[si]=c;S[c]++; Row[si]=r; D[si]=D[c]; U[D[c]]=si; U[si]=c; D[c]=si; if(H[r]<0) H[r]=L[si]=R[si]=si; else { R[si]=R[H[r]]; L[R[H[r]]]=si; L[si]=H[r]; R[H[r]]=si; } } void remove(int c) { for(int i=D[c];i!= c;i= D[i]) L[R[i]]=L[i],R[L[i]]=R[i]; } void resume(int c) { for(int i=U[c];i!= c;i=U[i]) L[R[i]]=R[L[i]]=i; } bool v[MNN]; int h() //估值 { int ret=0; for(int c=R[0];c!=0;c=R[c]) v[c]=1; for(int c=R[0];c!=0;c=R[c]) if(v[c]) { ret++; v[c]=0; for(int i=D[c];i!=c;i=D[i]) for(int j=R[i];j!=i;j=R[j]) v[Col[j]]=0; } return ret; } void dance(int d) { if(d+h()>=ansd) //利用A*优化 return; if(R[0]==0) { ansd=d; return; } int c=R[0]; for(int i=R[0];i!=0;i=R[i]) if(S[i]<S[c]) 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); dance(d+1); for(int j = L[i];j != i;j = L[j]) resume(j); resume(i); } } }dlx; const int M=20; int ti[M][M]; int p[M][M]; int main() { int n,m,n1,m1; while(scanf("%d%d",&n,&m)!=EOF) { int pp=0; //去掉多余的列 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&ti[i][j]); if(ti[i][j]) p[i][j]=++pp; } scanf("%d%d",&n1,&m1); dlx.init((n-n1+1)*(m-m1+1),pp); for(int ii=1;ii<=n-n1+1;ii++) for(int jj=1;jj<=m-m1+1;jj++) { int tmp=(ii-1)*(m-m1+1)+jj; for(int i=0;i<n1;i++) for(int j=0;j<m1;j++) if(ti[ii+i][jj+j]) dlx.link(tmp,p[ii+i][jj+j]); } dlx.ansd=1e9; dlx.dance(0); printf("%d\n",dlx.ansd);//一定存在最多次数 } return 0; }
FZU_1686_神龙的难题(DancingLinksX重复覆盖)
标签:
原文地址:http://blog.csdn.net/baidu_29410909/article/details/51288739