1066: [SCOI2007]蜥蜴
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 4139 Solved: 2093
[Submit][Status][Discuss]
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
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 4139 Solved: 2093
[Submit][Status][Discuss]
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
将每个高度大于0的点拆成两个点并连一条容量为h的边,对于距离d以内的点连一条容量为INF的边,源点向所有蜥蜴所在点 连一条容量为1的边,可以一步走出的点汇点连容量为INF的边,然后就是最大流了。
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int maxm = 100005;
const int INF = 1e9 + 7;
struct node
{
int data, flow, next;
}edge[maxm];
int map[30][30], head[maxm], dis[maxm], f[30][30], cur[maxm];
int n, m, s, t, cnt, d, id;
char str[30];
void init()
{
cnt = 0, id = 0;
memset(head, -1, sizeof(head));
}
void add(int u, int v, int w)
{
edge[cnt].data = v, edge[cnt].flow = w, edge[cnt].next = head[u], head[u] = cnt++;
edge[cnt].data = u, edge[cnt].flow = 0, edge[cnt].next = head[v], head[v] = cnt++;
}
void work(int x, int y)
{
if (x - d<1 || y - d<1 || x + d>n || y + d>m) add(map[x][y] + id, t, INF);
for (int i = max(1, x - d);i <= min(n, x + d);i++)
{
for (int j = max(1, y - d);j <= min(m, y + d);j++)
{
if (f[i][j] > 0 && abs(i - x) + abs(j - y) <= d)
add(map[x][y] + id, map[i][j], INF);
}
}
}
int bfs()
{
memset(dis, -1, sizeof(dis));
queue<int>q;
dis[s] = 0;
q.push(s);
while (!q.empty())
{
int u = q.front();q.pop();
for (int i = head[u];i != -1;i = edge[i].next)
{
int v = edge[i].data;
if (edge[i].flow > 0 && dis[v] == -1)
{
dis[v] = dis[u] + 1;
q.push(v);
}
}
}
if (dis[t] == -1) return 0;
return 1;
}
int dfs(int u, int flow)
{
if (u == t) return flow;
for (int i = cur[u];i != -1;i = edge[i].next)
{
int v = edge[i].data;
if (edge[i].flow&&dis[v] == dis[u] + 1)
{
int d = dfs(v, min(flow, edge[i].flow));
if (d > 0)
{
edge[i].flow -= d, edge[i ^ 1].flow += d;
return d;
}
}
}
return 0;
}
int dinic()
{
int ans = 0, d;
while (bfs())
{
for (int i = s;i <= t;i++) cur[i] = head[i];
while (d = dfs(s, INF) > 0)
ans += d;
}
return ans;
}
int main()
{
int i, j, k, sum = 0;
scanf("%d%d%d", &n, &m, &d);
init();
for (i = 1;i <= n;i++)
{
scanf("%s", str + 1);
for (j = 1;j <= m;j++)
{
f[i][j] = str[j] - '0';
if (f[i][j] > 0) map[i][j] = ++id;
}
}
s = 0, t = id * 2 + 1;
for (i = 1;i <= n;i++)
{
scanf("%s", str + 1);
for (j = 1;j <= m;j++)
if (str[j] == 'L') { sum++, add(s, map[i][j], 1); }
}
for (i = 1;i <= n;i++)
{
for (j = 1;j <= m;j++)
if (f[i][j] > 0)
{
add(map[i][j], map[i][j] + id, f[i][j]);
work(i, j);
}
}
printf("%d\n", sum - dinic());
return 0;
}