bzoj1066: [SCOI2007]蜥蜴

Description

在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。

Input

输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

Output

输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。

Sample Input

5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........

Sample Output

1

HINT

 

100%的数据满足:1<=r, c<=20, 1<=d<=4

 

题解:

把每个石柱i拆成两个点i1,i2,由i1向i2连容量为石柱高的边,如果i和j的距离不超过d,那么由i2向j1连容量为inf的边

如果能够从石柱i跳出,由i2向T连容量为inf的边

如果石柱上有蜥蜴,由S向i1连容量为1的边

然后答案为 蜥蜴数-最大流

code:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define maxn 850
 7 #define maxm 40000
 8 #define inf 1061109567
 9 using namespace std;
10 char ch;
11 bool ok;
12 void read(int &x){
13     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
14     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
15     if (ok) x=-x;
16 }
17 char h[22][22],exi[22][22];
18 int n,m,d;
19 struct flow{
20     int s,t,tot,now[maxn],son[maxm],pre[maxm],val[maxm];
21     int dis[maxn],head,tail,list[maxn];
22     bool bo[maxn];
23     void init(){s=0,t=1,tot=1,memset(now,0,sizeof(now));}
24     void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
25     void add(int a,int b,int c){put(a,b,c),put(b,a,0);}
26     bool bfs(){
27         memset(bo,0,sizeof(bo));
28         head=0,tail=1,list[1]=s,dis[s]=0,bo[s]=1;
29         while (head<tail){
30             int u=list[++head];
31             for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
32                 if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v;
33         }
34         return bo[t];
35     }
36     int dfs(int u,int rest){
37         if (u==t) return rest;
38         int ans=0;
39         for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])
40             if (val[p]&&dis[v]==dis[u]+1){
41                 int d=dfs(v,min(rest,val[p]));
42                 val[p]-=d,val[p^1]+=d,ans+=d,rest-=d;
43             }
44         if (!ans) dis[u]=-1;
45         return ans;
46     }
47     int dinic(){
48         int ans=0;
49         while (bfs()) ans+=dfs(s,inf);
50         return ans;
51     }
52 }f;
53 struct Point{
54     int x,y,dis;
55 }list[maxn];
56 bool bo[22][22];
57 const int dx[4]={1,0,-1,0};
58 const int dy[4]={0,1,0,-1};
59 int head,tail;
60 void bfs(int sx,int sy){
61     memset(bo,0,sizeof(bo));
62     int st=(sx-1)*m+sy;
63     bool flag=0;
64     head=0,tail=1,list[1]=(Point){sx,sy,0},bo[sx][sy]=1,f.add(st<<1,(st<<1)+1,h[sx][sy]-'0');
65     while (head<tail){
66         Point p=list[++head];
67         if (p.dis==d) continue;
68         for (int i=0;i<4;i++){
69             int x=p.x+dx[i],y=p.y+dy[i],t=(x-1)*m+y;
70             if (x<=0||x>n||y<=0||y>m){flag=1;continue;}
71             if (bo[x][y]) continue;
72             list[++tail]=(Point){x,y,p.dis+1},bo[x][y]=1;
73             if (h[x][y]!='0') f.add((st<<1)+1,t<<1,inf);
74         }
75     }
76     if (flag) f.add((st<<1)+1,f.t,inf);
77 }
78 int cnt;
79 int main(){
80     read(n),read(m),read(d),f.init();
81     for (int i=1;i<=n;i++) scanf("%s",h[i]+1);
82     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (h[i][j]!='0') bfs(i,j);
83     for (int i=1;i<=n;i++) scanf("%s",exi[i]+1);
84     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (exi[i][j]=='L') f.add(f.s,((i-1)*m+j)<<1,1),cnt++;
85     printf("%d\n",cnt-f.dinic());
86     return 0;
87 }

 

posted @ 2016-01-18 16:59  chenyushuo  阅读(151)  评论(0编辑  收藏  举报