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
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
Sample Output
HINT
100%的數據滿足:1<=r, c<=20, 1<=d<=4
bzoj上的第三道題目,第一道非水題......
其實就是一道簡單的最大流問題,關鍵是建模,建完模之後直接複製模板就行了
#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;
}