题意:在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1,如果该石柱原来高度为1,则蜥蜴离开后消失,以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。
每个柱子拆点限制容量,对每个点对从这个点能够到达的其他点暴力建图,源点连往所有初始有蜥蜴的点,设流量为1,对所有能跳到地图外的点连往汇点。
跑最大流即可。
#include <bits/stdc++.h>
using namespace std;
namespace dinic {
static const int maxn = 1100;
static const int maxm = 4e6+10;
struct Edge{
int u, v, next, flow, cap;
}edge[maxm];
int head[maxn], level[maxn], cur[maxn], eg;
void addedge(int u, int v, int cap) {
edge[eg] = {u, v, head[u], 0, cap}, head[u] = eg++;
swap(u, v);
edge[eg] = {u, v, head[u], 0, 0}, head[u] = eg++;
}
void init() {
eg = 0;
memset(head, -1, sizeof head);
}
bool makelevel(int s, int t, int n) {
for(int i = 0; i < n; i++) {
level[i] = 0; cur[i] = head[i];
}
queue<int> q; q.push(s);
level[s] = 1;
while(!q.empty()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = edge[i].next) {
Edge &e = edge[i];
if(e.flow < e.cap && level[e.v] == 0) {
level[e.v] = level[u] + 1;
if(e.v == t) return 1;
q.push(e.v);
}
}
}
return 0;
}
int findpath(int s, int t, int limit = INT_MAX) {
if(s == t || limit == 0) return limit;
for(int i = cur[s]; ~i; i = edge[i].next) {
cur[edge[i].u] = i;
Edge & e = edge[i], &rev = edge[i^1];
if(e.flow < e.cap && level[e.v] == level[s] + 1) {
int flow = findpath(e.v, t, min(limit, e.cap - e.flow));
if(flow > 0) {
e.flow += flow;
rev.flow -= flow;
return flow;
}
}
}
return 0;
}
int maxflow(int s, int t, int n) {
int ans = 0;
while(makelevel(s, t, n)) {
int flow = 0;
while((flow = findpath(s, t)) > 0) ans += flow;
}
return ans;
}
}
namespace solver {
int r, c, d;
int deg[22][22];
char g[22][22];
bool i_can_jump(int x, int y) {
if(x <= d || (r+1-x) <= d || y <= d || (c+1-y) <=d)
return 1;
return 0;
}
bool in(int x, int y, int px, int py) {
if(abs(px-x) + abs(py-y) <= d)
return 1;
return 0;
}
void solve() {
int s = 0, t = 1000;
int gap = 500;
dinic::init();
scanf("%d%d%d", &r, &c, &d);
int cnt = 0;
for(int i = 1; i <= r; i++)
for(int j = 1; j <= c; j++) {
char k;
scanf(" %c", &k);
deg[i][j] = k-'0';
if(i_can_jump(i, j) && deg[i][j])
dinic::addedge(gap + r*i+j, t, 0x3f3f3f3f);
if(deg[i][j])
dinic::addedge(r*i+j, gap + r*i+j, deg[i][j]);
}
for(int i = 1; i <= r; i++)
for(int j = 1; j <= c; j++) {
scanf(" %c", &g[i][j]);
if(g[i][j] == 'L' && deg[i][j])
dinic::addedge(s, r*i+j, 1), cnt++;
}
for(int i = 1; i <= r; i++)
for(int j = 1; j <= c; j++) {
for(int k = max(1, i-d); k <= min(r, i+d); k++) {
for(int p = max(1, j-d); p <= min(c, j+d); p++) {
if(in(i, j, k, p) && !(i==k&&j==p) && deg[i][j] && deg[k][p]) {
dinic::addedge(i*r+j+gap, k*r+p, 0x3f3f3f3f);
}
}
}
}
printf("%d\n", cnt - dinic::maxflow(s, t, t+1));
}
}
int main() {
solver::solve();
return 0;
}