正解是IDA*+四个方向判重,但由于是个裸的可重复覆盖问题,可以用DLX水过~
每个格子与放上皇后能干掉的标记连边,跑可重复覆盖DLX。注意要用IDA*来优化,否则会超时。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=10+2; 5 int n,m,np,ka; 6 char s[N][N]; 7 struct P {int x,y;} p[N*N]; 8 bool ok(P a,P b) { 9 if(a.x==b.x)return 1; 10 if(a.y==b.y)return 1; 11 if(abs(a.x-b.x)==abs(a.y-b.y))return 1; 12 return 0; 13 } 14 15 struct DLX { 16 static const int N=1000; 17 static const int M=1000; 18 static const int MX=10000; 19 int n,tot,S[M],H[N],vis[M]; 20 int row[MX],col[MX],L[MX],R[MX],U[MX],D[MX]; 21 void init(int _n) { 22 n=_n; 23 for(int i=0; i<=n; ++i) { 24 U[i]=D[i]=i; 25 L[i]=i-1,R[i]=i+1; 26 } 27 L[0]=n,R[n]=0; 28 tot=n+1; 29 memset(S,0,sizeof S); 30 memset(H,-1,sizeof H); 31 memset(vis,0,sizeof vis); 32 } 33 void link(int r,int c) { 34 int u=tot++; 35 S[c]++; 36 row[u]=r,col[u]=c; 37 U[u]=U[c],D[u]=c; 38 U[D[u]]=D[U[u]]=u; 39 if(!~H[r])H[r]=L[u]=R[u]=u; 40 else { 41 R[u]=H[r],L[u]=L[H[r]]; 42 L[R[u]]=R[L[u]]=u; 43 } 44 } 45 void remove(int c) { 46 for(int i=D[c]; i!=c; i=D[i])L[R[i]]=L[i],R[L[i]]=R[i]; 47 } 48 void restore(int c) { 49 for(int i=U[c]; i!=c; i=U[i])L[R[i]]=R[L[i]]=i; 50 } 51 int h() { 52 int ret=0; 53 for(int c=R[0]; c!=0; c=R[c])vis[c]=1; 54 for(int c=R[0]; c!=0; c=R[c])if(vis[c]) { 55 ++ret,vis[c]=0; 56 for(int i=D[c]; i!=c; i=D[i]) 57 for(int j=R[i]; j!=i; j=R[j])vis[col[j]]=0; 58 } 59 return ret; 60 } 61 void check() { 62 for(int c=1; c<=n; ++c)if(!S[c]) { 63 for(int i=D[c]; i!=c; i=D[i])L[R[i]]=L[i],R[L[i]]=R[i]; 64 L[R[c]]=L[c],R[L[c]]=R[c]; 65 } 66 } 67 bool dfs(int dep,int mxd) { 68 if(R[0]==0)return 1; 69 if(dep+h()>mxd)return 0; 70 int c=R[0]; 71 for(int i=R[0]; i!=0; i=R[i])if(S[i]<S[c])c=i; 72 for(int i=D[c]; i!=c; i=D[i]) { 73 remove(i); 74 for(int j=R[i]; j!=i; j=R[j])remove(j); 75 if(dfs(dep+1,mxd))return 1; 76 for(int j=L[i]; j!=i; j=L[j])restore(j); 77 restore(i); 78 } 79 return 0; 80 } 81 int IDAStar() {for(int mxd=0;; ++mxd) {if(dfs(0,mxd))return mxd;}} 82 } dlx; 83 84 int main() { 85 while(scanf("%d%d",&n,&m)&&n) { 86 np=0; 87 for(int i=0; i<n; ++i)scanf("%s",s[i]); 88 for(int i=0; i<n; ++i) 89 for(int j=0; j<m; ++j)if(s[i][j]=='X')p[np++]= {i,j}; 90 dlx.init(np); 91 for(int i=0; i<n; ++i) 92 for(int j=0; j<m; ++j) 93 for(int k=0; k<np; ++k) 94 if(ok({i,j}, p[k]))dlx.link(i*m+j+1,k+1); 95 printf("Case %d: %d ",++ka,dlx.IDAStar()); 96 } 97 return 0; 98 }