bzoj 1066 蜥蜴

最大流。

建图:首先将每根柱子拆成两个点。

每根柱子的入点向出点连一条容量为柱子高度的边。

每根柱子的出点向可以到达的柱子的入点连一条容量为正无穷的边。

源点向每根初始有蜥蜴的柱子的入点连一条容量为一的边。

每根可以跳出地图的柱子的出点向汇点连一条容量为正无穷的边。

跑一遍最大流就是最多能逃出的蜥蜴数。

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int dian=8005;
 9 const int bian=160005;
10 const int INF=0x3f3f3f3f;
11 int h[dian],nxt[bian],ver[bian],val[bian],ch[dian];
12 char mapp[25][25],map[25][25];
13 char lala[25];
14 int n,m,d,tot,ans;
15 int S,T;
16 void add(int aa,int bb,int cc){
17     tot++;ver[tot]=bb;nxt[tot]=h[aa];val[tot]=cc;h[aa]=tot;
18     tot++;ver[tot]=aa;nxt[tot]=h[bb];val[tot]=0;h[bb]=tot;
19 }
20 int bh(int aa,int bb,int cc){
21     return (aa-1)*m+bb+cc*n*m;
22 }
23 bool tell(){
24     memset(ch,-1,sizeof(ch));
25     queue<int>q;
26     q.push(S);
27     ch[S]=0;
28     while(!q.empty()){
29         int t=q.front();
30         q.pop();
31         for(int i=h[t];i;i=nxt[i])
32             if(ch[ver[i]]==-1&&val[i]){
33                 q.push(ver[i]);
34                 ch[ver[i]]=ch[t]+1;
35             }
36     }
37     return ch[T]!=-1;
38 }
39 int zeng(int a,int b){
40     if(a==T)
41         return b;
42     int r=0;
43     for(int i=h[a];i&&b>r;i=nxt[i])
44         if(ch[a]+1==ch[ver[i]]&&val[i]){
45             int t=zeng(ver[i],min(b-r,val[i]));
46             val[i]-=t,r+=t,val[i^1]+=t;
47         }
48     if(!r)
49         ch[a]=-1;
50     return r;
51 }
52 int dinic(){
53     int r=0,t;
54     while(tell())
55         while(t=zeng(S,INF))
56             r+=t;
57     return r;
58 }
59 int main(){
60     tot=1;
61     scanf("%d%d%d",&n,&m,&d);
62     S=2*n*m+1,T=2*n*m+2;
63     for(int i=1;i<=n;i++)
64         scanf("%s",mapp[i]+1);
65     for(int i=1;i<=n;i++)
66         for(int j=1;j<=m;j++)
67             map[i][j]=mapp[i][j]-'0';
68     for(int i=1;i<=n;i++)
69         for(int j=1;j<=m;j++)
70             if(map[i][j]){
71                 add(bh(i,j,0),bh(i,j,1),map[i][j]);
72                 for(int k=i-d;k<=i+d;k++)
73                     for(int l=j-d;l<=j+d;l++)
74                         if(k>=1&&k<=n&&l>=1&&l<=m&&(k!=i||l!=j)&&abs(k-i)*abs(k-i)+abs(l-j)*abs(l-j)<=d*d&&map[k][l])
75                             add(bh(i,j,1),bh(k,l,0),INF);
76             }
77     for(int i=1;i<=n;i++)
78         for(int j=1;j<=m;j++)
79             if(min(min(i,n+1-i),min(j,m+1-j))<=d&&map[i][j])
80                 add(bh(i,j,1),T,INF);
81     for(int i=1;i<=n;i++){
82         scanf("%s",lala+1);
83         for(int j=1;j<=m;j++)
84             if(lala[j]=='L'){
85                 ans++;
86                 add(S,bh(i,j,0),1);
87             }
88     }
89     printf("%d",ans-dinic());
90     return 0;
91 }

注意:

数组大小要好好算。

读入均为字符串形式。

距离为欧几里得距离。

 

posted @ 2016-12-23 15:58  dugudashen  阅读(148)  评论(0编辑  收藏  举报