[SCOI2007]蜥蜴

题目背景

07四川省选

题目描述

在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。

每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。

输入输出格式

输入格式:

输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石柱的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

输出格式:

输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。

输入输出样例

输入样例#1:
5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
输出样例#1:
1

说明

100%的数据满足:1<=r, c<=20, 1<=d<=3

题解:网络流

把每个点的权值转移到边上,即拆点,在两个点之间连一条为这个点的权值的边

把所有到这个点的入弧,连到原始点上,把出弧从拆的点发出,这就做到了把点的权值转移到边上

对于每两个能互相跳到的石柱,连权值为INF的边

建源点,汇点

因为每个点只有一只蜥蜴,连一条从源点到这个点权值为1的边   //做的过程中连了权值为INF的边,调了好久。。。

对于每个能令蜥蜴跳出地图的石柱,连一条从这个点到汇点权值为INF的边

跑一遍dinic,蜥蜴个数减最大流即为答案

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int INF=1999999999;
int r,c,d;int y=0;
int mp1[21][21];bool mp2[21][21];int mp3[21][21];
struct data{
int next,to,cap;
}g[200000];
int iter[1000],h[1000],level[1000],k=1,head,tail,q[1000];
void add(int from,int to,int cap)
{
g[++k].next=h[from];h[from]=k;g[k].to=to;g[k].cap=cap;
g[++k].next=h[to];h[to]=k;g[k].to=from;g[k].cap=0;
}
void bfs(int s)
{
memset(level,0,sizeof(level));
head=tail=0;q[tail++]=s;level[s]=1;
while(head!=tail)
{
int u=q[head++];
for(int i=h[u];i;i=g[i].next)
{
if(!level[g[i].to]&&g[i].cap)
{
level[g[i].to]=level[u]+1;q[tail++]=g[i].to;
}
}
}
}
int dfs(int u,int t,int f)
{
if(u==t)return f;
int used=0,w;
for(int &i=iter[u];i;i=g[i].next)
{
if(g[i].cap&&level[g[i].to]==level[u]+1)
{
w=f-used;w=dfs(g[i].to,t,min(w,g[i].cap));
if(w)
{
g[i].cap-=w;g[i^1].cap+=w;used+=w;if(used==f)return f;
}
}
}
return used;
}
int dinic(int s,int t)
{
int flow=0;
for(;;)
{
for(int i=1;i<=2*y+2;i++)iter[i]=h[i];
bfs(s);if(!level[t])return flow;
flow+=dfs(s,t,INF);
}
}
int main()
{
int gg=0;
scanf("%d%d%d",&r,&c,&d);
for(int i=1;i<=r;i++)
{
char cc[21];scanf("%s",cc);
for(int j=1;j<=c;j++)mp1[i][j]=cc[j-1]-'0';
}
for(int i=1;i<=r;i++)
{
char cc[21];scanf("%s",cc);
for(int j=1;j<=c;j++)
{
if(cc[j-1]=='L')mp2[i][j]=1,gg++;
else mp2[i][j]=0;
}
}
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
if(mp1[i][j])mp3[i][j]=++y;
}
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
for(int k1=1;k1<=r;k1++)
for(int k2=1;k2<=c;k2++)
{
if(k1==i&&k2==j)continue;
if((k1-i)*(k1-i)+(k2-j)*(k2-j)<=d*d&&mp1[i][j]&&mp1[k1][k2])
{add(mp3[i][j]+y,mp3[k1][k2],INF);add(mp3[k1][k2]+y,mp3[i][j],INF);}
}
if(mp1[i][j])add(mp3[i][j],mp3[i][j]+y,mp1[i][j]);
if(mp2[i][j])add(2*y+1,mp3[i][j],1);
for(int k1=0;k1<=r+1;k1++)
for(int k2=0;k2<=c+1;k2++)
{
if((k1==0||k1==r+1||k2==0||k2==c+1)&&(k1-i)*(k1-i)+(k2-j)*(k2-j)<=d*d&&mp1[i][j])
{add(mp3[i][j]+y,2*y+2,INF);}
}
}
cout<<gg-dinic(2*y+1,2*y+2);
return 0;
}
原文地址:https://www.cnblogs.com/lher/p/6550224.html