SCOI2007]蜥蜴
Time Limit:1000MS Memory Limit:165536K
Total Submit:44 Accepted:29
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<=3
Source
Pku 2711 Leapin’ Lizards
有点水的网络流,直接拆点构图就可以了。。
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cstring>
#include<cmath>
#define rep(i,n) for(int i=0;i<n;i++)
#define pb push_back
using namespace std;
typedef pair<int,int> ii;
const int inf=~0U>>1,maxn=20,maxv=maxn*maxn*2+2;
int n,m;
inline int In(int i,int j){return (i*m+j)*2;}
inline int Out(int i,int j){return In(i,j)+1;}
struct Edge
{
int t,c;
Edge*next,*op;
Edge(int _t,int _c,Edge*_next):t(_t),c(_c),next(_next){}
}*E[maxv]={0};
int h[maxv],vh[maxv],vs,vt,v;
void InsEdge(int s,int t,int c)
{
E[s]=new Edge(t,c,E[s]);
E[t]=new Edge(s,0,E[t]);
E[s]->op=E[t];E[t]->op=E[s];
}
int aug(int no,int m)
{
if(no==vt) return m;
int l=m;
for(Edge*i=E[no];i;i=i->next)if(i->c&&h[no]==h[i->t]+1)
{
int d=aug(i->t,min(i->c,l));
l-=d,i->c-=d,i->op->c+=d;
if(l==0||h[vs]>=v)return m-l;
}
int minh=v;
for(Edge*i=E[no];i;i=i->next)if(i->c&&h[i->t]+1<minh)
minh=h[i->t]+1;
if(–vh[h[no]]==0) h[vs]=v;vh[h[no]=minh]++;
return m-l;
}
int CalFlow()
{
memset(h,0,sizeof(h));
memset(vh,0,sizeof(vh));
vh[0]=v;
int flow=0;while(h[vs]<v)flow+=aug(vs,inf);
return flow;
}
inline int Dist(ii a,ii b){return abs(a.first-b.first)+abs(a.second-b.second);}
inline int DistToExit(int x,int y){return min(x+1,min(n-x,min(y+1,m-y)));}
int main()
{
//freopen("in","r",stdin);
int x,d,a=0;char c;cin>>n>>m>>d;v=n*m*2+2;vs=v-1;vt=vs-1;
rep(i,n)rep(j,m){cin>>c;x=c-‘0’;if(x)InsEdge(In(i,j),Out(i,j),x);}
rep(i,n)rep(j,m){cin>>c;if(c==’L’) InsEdge(vs,In(i,j),1),a++;}
rep(i,n)rep(j,m)rep(a,n)rep(b,m)if(Dist(ii(i,j),ii(a,b))<=d) InsEdge(Out(i,j),In(a,b),inf);
rep(i,n)rep(j,m)if(DistToExit(i,j)<=d) InsEdge(Out(i,j),vt,inf);
cout<<a-CalFlow()<<endl;
}

