1066: [SCOI2007]蜥蜴
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3916 Solved: 1965
[ 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..
........
........
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
Sample Output
1
HINT
100%的数据满足:1<=r, c<=20, 1<=d<=4
bzoj上的第三道题目,第一道非水题......
其实就是一道简单的最大流问题,关键是建模,建完模之后直接复制模板就行了
把每两个石柱之间看做是一个点,石柱的高度就是这两个节点的容量
如图,a和b之间容量为3,b和c之间容量为2
下面是代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string.h>
#include <cmath>
#include <queue>
#define maxn 821396745
using namespace std;
int ans,tot,fin[1010][1010];
char high[1010][1010];
int n,m,s,t,f[11000],flow[11000],d,map[1000][1000];
queue <int> q;
void make(int x,int y)
{
int now=fin[x][y]+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if((i!=x||j!=y)&&(high[i][j]>'0'))
{
if(d>=sqrt((x-i)*(x-i)+(y-j)*(y-j)))
map[now][fin[i][j]]=maxn;
}
}
void go()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(i-d<1||i+d>n||j-d<1||j+d>m)
{
int de=fin[i][j]+1;
map[de][tot]=maxn;
}
}
int bfs(int s,int t)
{
while(!q.empty())
q.pop();
memset(f,-1,sizeof(f));
f[s]=0;
flow[s]=maxn;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
if(u==t) break;
for(int v=1;v<=tot;v++)
{
if(map[u][v]>0&&f[v]==-1)
{
f[v]=u;
flow[v]=min(flow[u],map[u][v]);
q.push(v);
}
}
}
if(f[t]==-1)
return -1;
else
return flow[t];
}
int maxflow(int s,int t)
{
int maxf=0;
d=0;
while((d=bfs(s,t))!=-1)
{
int aim=t;
while(aim!=s)
{
map[f[aim]][aim]-=d;
map[aim][f[aim]]+=d;
aim=f[aim];
}
maxf+=d;
}
return maxf;
}
int main()
{
scanf("%d%d%d",&n,&m,&d);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>high[i][j];
if(high[i][j]!='0')
{
fin[i][j]=++tot;
map[tot][++tot]=high[i][j]-'0';
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
char cp;
cin>>cp;
if(cp=='L')
{
ans++;
map[0][fin[i][j]]=1;
}
if(high[i][j]>'0')
make(i,j);
}
tot++;
go();
printf("%d",ans-maxflow(0,tot));
return 0;
}