UVA - 11214 Guarding the Chessboard (可重复覆盖,DLX+IDA*)

题目链接

正解是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\n",++ka,dlx.IDAStar());
96     }
97     return 0;
98 }

 

posted @ 2019-02-14 16:18  jrltx  阅读(234)  评论(0编辑  收藏  举报