bzoj1066 蜥蜴
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
虽然它需要每个蜥蜴不能同时在同一石柱上,但是实际上我们可以让蜥蜴按一定顺序一个一个走,不同时走。那这些排列顺序里一定有一种方案是最优的。
为什么呢?因为最优解不可能出现蜥蜴A跳出去的路径中经过蜥蜴B的初始位置(标记为A->B),并且蜥蜴B跳出去的路径中经过蜥蜴A的初始位置(标记为B->A)。
也就是说要么蜥蜴A跳出去的路径中经过蜥蜴B的初始位置,那么蜥蜴B应该排在蜥蜴A前面走;要么蜥蜴B跳出去的路径中要经过蜥蜴A的初始位置,那么蜥蜴A应该排在蜥蜴B前走。
同样更不会出现A->B且B->C且C->A的情况、A->B且B->C且C->D且D->A的情况,等等。也就是说这个一定是有拓扑序的,不会有环。
那么我们在跑网络流的时候可以不用管它的顺序,直接跑最大流,只要是可行流就一定是可行解,因为一定会有一个蜥蜴的排列顺序满足这个可行流。每个石柱拆成两个点,这两个点间连一条最大流量为石柱高度的点,从S向每个蜥蜴所在石柱连一条最大流量为1的边。T与每个能跳出地图的石柱连一条最大流量为INF的边。石柱与石柱间若距离<=d也相互连最大流量为INF的边。
所以就拆点Dinic。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=400*2+10,maxm=maxn*maxn,INF=0x3f3f3f3f;
int n,r,c,d,tot_col,tot_m,sz,S,T;
int bh[maxn][maxn];
char kk;
struct Col{
int x,y,h;
}col[maxn];
int aa,ff;char cc;
int read() {
aa=0;ff=1;cc=getchar();
while(cc<'0'||cc>'9') {
if(cc=='-') ff=-1;
cc=getchar();
}
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*ff;
}
struct Node{
int x,y,flow,cap;
Node(){}
Node(int x,int y,int cap):x(x),y(y),cap(cap){flow=0;}
}node[2*maxm];
int cur[maxn],fir[maxn],nxt[2*maxm],e=1;
void add(int x,int y,int z) {
node[++e]=Node(x,y,z); nxt[e]=fir[x];fir[x]=e;
node[++e]=Node(y,x,0); nxt[e]=fir[y];fir[y]=e;
}
int dis[maxn],zz[maxn];
bool BFS() {
int s=1,t=0,x,y,z;
memset(dis,-1,sizeof(dis));
dis[S]=0;zz[++t]=S;
while(s<=t) {
x=zz[s];
for(y=fir[x];y;y=nxt[y]) {
z=node[y].y;
if(dis[z]!=-1||node[y].flow>=node[y].cap) continue;
dis[z]=dis[x]+1;
zz[++t]=z;
}
s++;
}
return dis[T]!=-1;
}
int DFS(int pos,int maxf) {
if(pos==T||!maxf) return maxf;
int now,z,rs=0;
for(int &y=cur[pos];y;y=nxt[y]) {
z=node[y].y;
if(dis[z]!=dis[pos]+1||node[y].flow>=node[y].cap) continue;
now=DFS(z,min(maxf,node[y].cap-node[y].flow));
node[y].flow+=now; node[y^1].flow-=now;
maxf-=now; rs+=now;
}
if(!rs) dis[pos]=-1;
return rs;
}
int Dinic() {
int rs=0;
while(BFS()) {
memcpy(cur,fir,sizeof(fir));
rs+=DFS(S,INF);
}
return rs;
}
bool ok(int x,int y) {
return sqrt((double)(col[x].x-col[y].x)*(col[x].x-col[y].x)+(double)(col[x].y-col[y].y)*(col[x].y-col[y].y))<=(double)d;
}
int main() {
r=read();c=read();d=read(); int x;
for(int i=1;i<=r;++i) {
kk=getchar();
while(kk<'0'||kk>'9') kk=getchar();
x=kk-'0';
for(int j=1;j<=c;++j) {
if(x) {
col[++tot_col].x=i;
col[tot_col].y=j;
col[tot_col].h=x;
bh[i][j]=tot_col;
}
kk=getchar();x=kk-'0';
}
}
S=2*tot_col+1;T=S+1;
for(int i=1;i<=tot_col;++i) {
add(i,i+tot_col,col[i].h);
if(min(col[i].x,r-col[i].x+1)<=d||min(col[i].y,c-col[i].y+1)<=d) add(i+tot_col,T,INF);
for(int j=1;j<=tot_col;++j){
if(i==j) continue;
else if(ok(i,j)) add(i+tot_col,j,INF);
}
}
for(int i=1;i<=r;++i) {
kk=getchar();
while(kk!='.'&&kk!='L') kk=getchar();
for(int j=1;j<=c;++j) {
if(kk=='L')
add(S,bh[i][j],1),n++;
kk=getchar();
}
}
printf("%d",n-Dinic());
return 0;
}

浙公网安备 33010602011771号