Since time is limited, bomberman has to do this job quite efficiently. Now he has successfully defeated all the foes, and is searching for the exit. It's really troublesome to destroy the walls one by one, so he's asking for your help to calculate the minimal number of bombs he has to place in order to destroy all the walls, thus he can surely find the exit.
9 11 *********** *#.#...#.#* *.*.*.*.*.* *.........* *.*.*.*.*.* *....#....* *.*.*.*.*.* *....#....* *********** 3 13 ************* *..##...##..* *************
33
题意:如图中所示,‘#’是可摧毁的墙,‘*’不可摧毁的墙,‘.’为空地,在空地上放炸弹可以炸毁同行同列的墙,但是不可摧毁的墙是炸不动的,问;在最开始的局面上最少同时放几个炸弹可以把所有#炸毁
思路:典型的舞蹈链可重复覆盖问题,以#为列(需要标序号),以能够炸毁墙的空地为行,然后就是舞蹈链模板喽
兴奋啊,这是独立完成的第一道舞蹈链的问题,纪念一下
ac代码:
#include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int inf=0x3f3f3f3f; const ll INF=0x3f3f3f3f3f3f3f3fll; const int maxn=260; int L[maxn*maxn],R[maxn*maxn],U[maxn*maxn],D[maxn*maxn]; int C[maxn*maxn],H[maxn],cnt[maxn],vis[maxn]; int n,m,id,fans; void init(int ll) { for(int i=0; i<=ll; i++) { cnt[i]=0; U[i]=D[i]=i; L[i+1]=i; R[i]=i+1; } R[ll]=0; id=ll+1; memset(H,-1,sizeof(H)); } void Link(int r,int c) { cnt[c]++; C[id]=c; U[id]=U[c]; D[U[c]]=id; D[id]=c; U[c]=id; if(H[r]==-1) H[r]=L[id]=R[id]=id; else { L[id]=L[H[r]]; R[L[H[r]]]=id; R[id]=H[r]; L[H[r]]=id; } 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=D[Size]; j!=Size; j=D[j]) L[R[j]]=R[L[j]]=j; } int h() { int sum=0; memset(vis,0,sizeof(vis)); for(int i=R[0]; i; i=R[i]) { if(vis[i]) continue; sum++; for(int j=D[i]; j!=i; j=D[j]) { for(int k=R[j]; k!=j; k=R[k]) vis[C[k]]=1; } } return sum; } void Dance(int k) { int mm=maxn,pos; if(k+h()>=fans) return; if(!R[0]) { if(k<fans) fans=k; return; } for(int i=R[0]; i; i=R[i]) if(mm>cnt[i]) mm=cnt[i],pos=i; for(int i=D[pos]; i!=pos; i=D[i]) { Remove(i); for(int j=R[i]; j!=i; j=R[j]) Remove(j); Dance(k+1); for(int j=R[i]; j!=i; j=R[j]) Resume(j); Resume(i); } } int B[20][20]; char A[20][20]; int main() { int u,v,len,wid; while(scanf("%d%d",&n,&m)!=-1) { getchar(); for(int i=0;i<n;i++) gets(A[i]); int kk=0; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(A[i][j]=='#') B[i][j]=(++kk); } } init(kk); int kkk=1; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(A[i][j]=='.') { for(int k=i;k<n;k++) { if(A[k][j]=='#') { Link(kkk,B[k][j]); break; } if(A[k][j]=='*') break; } for(int k=i;k>=0;k--) { if(A[k][j]=='#') { Link(kkk,B[k][j]); break; } if(A[k][j]=='*') break; } for(int k=j;k<m;k++) { if(A[i][k]=='#') { Link(kkk,B[i][k]); break; } if(A[i][k]=='*') break; } for(int k=j;k>=0;k--) { if(A[i][k]=='#') { Link(kkk,B[i][k]); break; } if(A[i][k]=='*') break; } } kkk++; } } fans=kkk-1; Dance(0); printf("%d\n",fans); } return 0; }