您的位置:首页 > 其它

【最大流】[SCOI2007]蜥蜴 BZOJ 1066

2013-05-14 14:26 501 查看

[SCOI2007]蜥蜴 BZOJ 1066

Time Limit: 1 Sec  Memory Limit:162 MB

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

说实话,没有经验还真看不出来

不过一旦看出来了就恍然大悟了,每个点拆成两个点(上下),可以理解成石柱上部和下部,然后从上部到下部连一条边,权值为高度(很巧妙)

然后源点和有蜥蜴的点连边,正无穷,然后边缘可以出去的石柱和汇点连边,正无穷

可以互相到达的石柱连边,正无穷

应该很好理解(想出来了以后)

然后跑一次sap(仍然是优化后的),ok

测评情况(BZOJ)



C++ AC Code

/*http://blog.csdn.net/jiangzh7
By Jiangzh*/
#include<cstdio>
#include<cmath>
#define min(a,b) ((a)<(b)?(a):(b))
const int N=20+10;
const int NN=N*N;
const int inf=0x3f3f3f3f;
int n,m,d,lizard_tot;
int height

,lizard

;
int g[NN][NN],S,T;
int v[NN],h[NN];

inline int IN(int x,int y){return (x*m+y)*2+1;}
inline int OU(int x,int y){return (x*m+y)*2+2;}

void read()
{
scanf("%d%d%d",&n,&m,&d);
char s[100];
for(int i=0;i<n;i++)
{
scanf("%s",s);
for(int j=0;j<m;j++)
height[i][j]=s[j]-'0';
}
for(int i=0;i<n;i++)
{
scanf("%s",s);
for(int j=0;j<m;j++)
{
lizard[i][j]=(s[j]=='L');
if(lizard[i][j]) lizard_tot++;
}
}
}

inline void inlink(int x,int y,int flow) { g[x][y]=flow; }
inline int dis(int x1,int y1,int x2,int y2)
{
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}

void build_map()
{
S=OU(n-1,m-1)+1; T=OU(n-1,m-1)+2;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(lizard[i][j]) inlink(S,IN(i,j),1);
if(height[i][j])
{
inlink(IN(i,j),OU(i,j),height[i][j]);
if(i<d||i>=n-d||j<d||j>=m-d)
inlink(OU(i,j),T,inf);
for(int x=0;x<n;x++)
for(int y=0;y<m;y++)
{
if(i==x && j==y) continue;
if(!height[x][y]) continue;
if(dis(i,j,x,y)<=d*d)
inlink(OU(i,j),IN(x,y),inf);
}
}
}
}

int sap(int x,int flow)
{
if(x==T) return flow;
int res=0;
for(int i=0;i<=T;i++)
if(g[x][i] && h[x]==h[i]+1)
{
int t=sap(i,min(g[x][i],flow-res));
g[x][i]-=t; g[i][x]+=t;
if((res+=t)==flow) return res;
if(h[S]>=T) return res;
}
if(!(--v[h[x]])) h[S]=T;
++v[++h[x]];
return res;
}

void work()
{
build_map();
int res=0;
v[S]=T;
while(h[S]<T) res+=sap(S,inf);
printf("%d\n",lizard_tot-res);
}

int main()
{
freopen("lizard.in","r",stdin);
freopen("lizard.out","w",stdout);
read();
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: