【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..
........
........
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
Sample Output
1
HINT
100%的数据满足:1<=r, c<=20, 1<=d<=4
Solution
最大流。
拆点,将一个点拆成两个点,一个点表示进来,另一个点表示出去。进来出去的点的个数不能超过数字个数。然后距离d以内的连一下最后流一下就好了。
Code
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 #include <queue> 6 7 #ifdef WIN32 8 #define LL "%I64d" 9 #else 10 #define LL "%lld" 11 #endif 12 13 #ifdef CT 14 #define debug(...) printf(__VA_ARGS__) 15 #define setfile() 16 #else 17 #define debug(...) 18 #define filename "" 19 #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout) 20 #endif 21 22 #define R register 23 #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) 24 #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) 25 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) 26 #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) 27 #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) 28 #define cabs(_x) ((_x) < 0 ? (- (_x)) : (_x)) 29 char B[1 << 15], *S = B, *T = B; 30 inline int F() 31 { 32 R char ch; R int cnt = 0; R bool minus = 0; 33 while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; 34 ch == '-' ? minus = 1 : cnt = ch - '0'; 35 while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; 36 return minus ? -cnt : cnt; 37 } 38 #define maxn 30 39 #define maxp 10010 40 #define maxm 1000010 41 #define inf 0x7fffffff 42 char mp[maxn][maxn], mp2[maxn][maxn]; 43 int id[maxn][maxn][2], id2[maxn][maxn]; 44 struct Edge 45 { 46 Edge *next, *rev; 47 int to, cap; 48 }*last[maxp], *cur[maxp], e[maxm], *ecnt = e; 49 int dep[maxp], s, t, ans; 50 std::queue<int> q; 51 inline void link(R int a, R int b, R int w) 52 { 53 // printf("%d %d %d\n", a, b, w ); 54 *++ecnt = (Edge) {last[a], ecnt + 1, b, w}; last[a] = ecnt; 55 *++ecnt = (Edge) {last[b], ecnt - 1, a, 0}; last[b] = ecnt; 56 } 57 inline bool bfs() 58 { 59 memset(dep, -1, sizeof (dep)); 60 dep[t] = 0; q.push(t); 61 while (!q.empty()) 62 { 63 R int now = q.front(); q.pop(); 64 for (R Edge *iter = last[now]; iter; iter = iter -> next) 65 { 66 R int pre = iter -> to; 67 if (dep[pre] == -1 && iter -> rev -> cap) 68 { 69 dep[pre] = dep[now] + 1; 70 q.push(pre); 71 } 72 } 73 } 74 return dep[s] != -1; 75 } 76 int dfs(R int x, R int f) 77 { 78 if (x == t) return f; 79 R int used = 0; 80 for (R Edge* &iter = cur[x]; iter; iter = iter -> next) 81 { 82 R int pre = iter -> to; 83 if (iter -> cap && dep[x] == dep[pre] + 1) 84 { 85 R int v = dfs(pre, dmin(iter -> cap, f - used)); 86 iter -> cap -= v; 87 iter -> rev -> cap += v; 88 used += v; 89 if (f == used) return f; 90 } 91 } 92 if (!used) dep[x] = -1; 93 return used; 94 } 95 inline void dinic() 96 { 97 while (bfs()) 98 { 99 memcpy(cur, last, sizeof last); 100 ans += dfs(s, inf); 101 } 102 } 103 int main() 104 { 105 // setfile(); 106 R int n = F(), m = F(), k = F(), cnt = 0, tot = 0; 107 for (R int i = 1; i <= n; ++i, getc()) 108 for (R int j = 1; j <= m; ++j) 109 { 110 mp[i][j] = getc(); 111 if (mp[i][j] > '0') 112 { 113 id[i][j][0] = ++cnt; 114 id[i][j][1] = ++cnt; 115 link(cnt - 1, cnt, mp[i][j] - '0'); 116 } 117 } 118 // for (R int i = 1; i <= n; ++i) puts(mp[i] + 1); 119 for (R int i = 1; i <= n; ++i, getc()) 120 for (R int j = 1; j <= m; ++j) 121 { 122 mp2[i][j] = getc(); 123 mp2[i][j] == 'L' ? ++tot : 0; 124 } 125 t = ++cnt; 126 for (R int i = 1; i <= n; ++i) 127 for (R int j = 1; j <= m; ++j) 128 if (mp[i][j] > '0') 129 { 130 for (R int ii = -k; ii <= k; ++ii) 131 for (R int jj = -k; jj <= k; ++jj) 132 if (i + ii > 0 && i + ii <= n && j + jj > 0 && j + jj <= m && !(ii == 0 && jj == 0) && mp[i + ii][j + jj] > '0' && ii * ii + jj * jj <= k * k) 133 link(id[i][j][1], id[i + ii][j + jj][0], inf); 134 if (dmin(i, n - i + 1) <= k || dmin(j, m - j + 1) <= k) 135 link(id[i][j][1], t, inf); 136 } 137 for (R int i = 1; i <= n; ++i) 138 for (R int j = 1; j <= m; ++j) 139 if (mp2[i][j] == 'L') 140 link(s, id[i][j][0], 1); 141 dinic(); 142 printf("%d\n", tot - ans ); 143 return 0; 144 } 145 /* 146 5 8 2 147 00000000 148 02000000 149 00321100 150 02000000 151 00000000 152 ........ 153 ........ 154 ..LLLL.. 155 ........ 156 ........ 157 */