您的位置:首页 > 其它

bzoj1066 (最大流)

2015-12-08 19:31 190 查看

1066: [SCOI2007]蜥蜴

Time Limit: 1 Sec Memory Limit: 162 MB

Submit: 2497 Solved: 1233

[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..

........

........

Sample Output

1

解题思路:

首先这道题可以看出是最大流,然后这道题特殊的是点上也有限制,所以对于每个点拆成两个,再建一条唯一的边,跑一边最大流。

#include<cstdio>

#include<iostream>

#include<cstring>

#include<algorithm>

using namespace std;

int n,m,d;

int len=1;

struct data

{

int to,v,next;

}e[500001];

int h[1000];

int dis[1000];

int q[100000];

int zhi[30][30];

int mark[30][30];

void insert(int x,int y,int w){++len; e[len].to=y; e[len].v=w; e[len].next=h[x]; h[x]=len;}

bool bfs()

{

memset(dis,-1,sizeof(dis));

int tail=1; int head=0; q[tail]=0; dis[0]=0;

while (head<tail)

{

++head;

int u=h[q[head]];

while (u!=-1)

{

if (dis[e[u].to]==-1 && e[u].v)

{

dis[e[u].to]=dis[q[head]]+1;

++tail; q[tail]=e[u].to;

}

u=e[u].next;

}

}

if (dis[801]==-1) return 0;else return 1;

}

int dinic(int now,int sum)

{

if (now==801) return sum;

int u=h[now]; int used=0;

while (u!=-1)

{

if (dis[e[u].to]==dis[now]+1 && e[u].v)

{

int w=dinic(e[u].to,min(sum-used,e[u].v));

used+=w;

e[u].v-=w; e[u^1].v+=w;

if (used==sum) return sum;

}

u=e[u].next;

}

if (used==0) dis[now]=-1;

return used;

}

int main()

{

scanf("%d %d %d",&n,&m,&d);

memset(h,-1,sizeof(h));

char c[21]; int tot=0;

for (int i=1;i<=n;++i)

{

scanf("%s",c);

for (int j=1;j<=m;++j)

{

int g=int(c[j-1])-48;

zhi[i][j]=g;

++tot; insert(tot,tot+1,g);

++tot; insert(tot,tot-1,0); mark[i][j]=tot-1;

}

}

for (int i=1;i<=n;++i)

for (int j=1;j<=m;++j)

for (int x1=1;x1<=n;++x1)

for (int y1=1;y1<=m;++y1)

if (i!=x1 || y1!=j)

if (abs(i-x1)+abs(j-y1)<=d && zhi[i][j] && zhi[x1][y1])

{

insert(mark[i][j]+1,mark[x1][y1],zhi[i][j]); insert(mark[x1][y1],mark[i][j]+1,0);

}

int ass=0;

for (int i=1;i<=n;++i)

{

scanf("%s",c);

for (int j=1;j<=m;++j)

{

if (j<=d || i<=d || (m-j+1)<=d || (n-i+1)<=d && zhi[i][j]) {insert(mark[i][j]+1,801,0x7fffffff);insert(801,mark[i][j]+1,0);}

if (c[j-1]=='L')++ass;

if (c[j-1]=='L' && zhi[i][j])

{

insert(0,mark[i][j],1); insert(mark[i][j],0,0);

}

}

}

int ans=0;

while (bfs())

{

ans+=dinic(0,0x7fffffff);

}

cout<<ass-ans;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: