【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

 

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 */

 

posted @ 2017-03-26 13:10  cot  阅读(172)  评论(0编辑  收藏  举报