蜥蜴 BZOJ 1066
蜥蜴
【问题描述】
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。
【输入格式】
输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。
【输出格式】
输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。
【样例输入】
5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
【样例输出】
1
【数据范围】
100%的数据满足:1<=r, c<=20, 1<=d<=4
题解:
题目中石柱的高度其实就是限制了点的通过次数
那么把每一个点拆成两个点,分别是进入点和离开点
每个进入点向对应的离开点连一条容量为石柱高度的边
每个离开点向能跳到的进入点连一条容量为无限的边
源点向每个有蜥蜴的进入点连一条容量为1的边
每个能跳出边界的离开点向汇点连一条容量为无限的边
跑一遍最大流
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdlib>
5 #include<cstdio>
6 #include<cmath>
7 using namespace std;
8 inline int Get()
9 {
10 int x;
11 char c;
12 while((c = getchar()) < '0' || c > '9');
13 x = c - '0';
14 while((c = getchar()) >= '0' && c <= '9') x = x * 10 + c - '0';
15 return x;
16 }
17 const int inf = 2147483647;
18 const int me = 100233;
19 int r, c, d, n;
20 int num;
21 int S, T;
22 struct shape
23 {
24 int x, y;
25 };
26 shape pos[me];
27 int point[1001][1001];
28 int tot = 1, nex[me], fir[me], to[me], val[me];
29 inline void Add(const int &x, const int &y, const int &z)
30 {
31 nex[++tot] = fir[x];
32 fir[x] = tot;
33 to[tot] = y;
34 val[tot] = z;
35 }
36 inline void Ins(const int &x, const int &y, const int &z)
37 {
38 Add(x, y, z);
39 Add(y, x, 0);
40 }
41 inline int Min(const int &x, const int &y)
42 {
43 return (x < y) ? x : y;
44 }
45 inline int Sqr(const int &x)
46 {
47 return x * x;
48 }
49 int dep[me], que[me];
50 inline bool Bfs()
51 {
52 int t = 0, w = 0;
53 memset(dep, -1, sizeof(dep));
54 que[++w] = S;
55 dep[S] = 1;
56 while(t < w)
57 {
58 int u = que[++t];
59 for(int i = fir[u]; i; i = nex[i])
60 {
61 int v = to[i];
62 if(dep[v] == -1 && val[i])
63 {
64 dep[v] = dep[u] + 1;
65 que[++w] = v;
66 if(v == T) return true;
67 }
68 }
69 }
70 return false;
71 }
72 int Dinic(const int &u, const int &flow)
73 {
74 if(u == T || !flow) return flow;
75 int wa = 0;
76 for(int i = fir[u]; i; i = nex[i])
77 {
78 int v = to[i];
79 if(dep[v] == dep[u] + 1 && val[i])
80 {
81 int go = Dinic(v, Min(flow - wa, val[i]));
82 if(go)
83 {
84 val[i] -= go;
85 val[i ^ 1] += go;
86 wa += go;
87 if(wa == flow) break;
88 }
89 }
90 }
91 return wa;
92 }
93 char s[me];
94 int main()
95 {
96 r = Get(), c = Get(), d = Get();
97 n = r * c;
98 S = 0, T = n << 1 | 1;
99 for(int i = 1; i <= r; ++i)
100 {
101 scanf("%s", s);
102 for(int j = 1; j <= c; ++j)
103 {
104 int sa = s[j - 1] - '0';
105 if(sa)
106 {
107 point[i][j] = ++num;
108 pos[num] = (shape) {i, j};
109 Ins(num, num + n, sa);
110 int dis = Min(i, Min(j, Min(r - i + 1, c - j + 1)));
111 if(dis <= d) Ins(num + n, T, inf);
112 for(int k = 1; k < num; ++k)
113 {
114 int x = pos[k].x, y = pos[k].y;
115 double dist = sqrt(Sqr(x - i) + Sqr(y - j));
116 if(dist <= d)
117 {
118 Ins(point[x][y] + n, num, inf);
119 Ins(num + n, point[x][y], inf);
120 }
121 }
122 }
123 }
124 }
125 int ans = 0;
126 for(int i = 1; i <= r; ++i)
127 {
128 scanf("%s", s);
129 for(int j = 1; j <= c; ++j)
130 if(s[j - 1] == 'L')
131 {
132 ++ans;
133 Ins(S, point[i][j], 1);
134 }
135 }
136 while(Bfs()) ans -= Dinic(S, inf);
137 printf("%d", ans);
138 }