BZOJ 1066: [SCOI2007]蜥蜴

1066: [SCOI2007]蜥蜴

Time Limit: 1 Sec  Memory Limit: 162 MB

Submit: 4298  Solved: 2181

[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

HINT

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

Source

Pku 2711 Leapin' Lizards

题解

每个石柱有次数限制,那么考虑网络流建图。

将石柱拆成两个点,连一条边,流量为石柱的高度,再在互相能到达的石柱之间连边,流量为inf,源点向每个蟋蟀所在的石柱连边,流量为1,能跳出边界的石柱向汇点连边,流量为inf。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int N=25,inf=0x3f3f3f3f;
int r,c,d,s,t,sz,k,ans,tot;
int id[N][N],head[N*N*2],vis[N*N*2],dis[N*N*2],cur[N*N*2];
struct node{
	int p1,p2,x,y,h;
}a[N*N];
struct edge{
	int u,v,flow,next;
}e[N*N*400];
int sqr(int x){
	return x*x;
}
double dist(node a,node b){
	return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
void addedge(int u,int v,int flow){
	e[k]=(edge){u,v,flow,head[u]};
	head[u]=k++;
	e[k]=(edge){v,u,0,head[v]};
	head[v]=k++;
}
queue<int>q;
bool bfs(){
	for(int i=1;i<=sz;i++){
		vis[i]=0;
		dis[i]=inf;
	}
	dis[s]=0;
	q.push(s);
	vis[s]=1;
	int u,v,flow;
	while(!q.empty()){
		u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i!=-1;i=e[i].next){
			v=e[i].v,flow=e[i].flow;
			if(flow&&dis[u]+1<dis[v]){
				dis[v]=dis[u]+1;
				if(!vis[v]){
					q.push(v);
					vis[v]=1;
				}
			}
		}
	}
	if(dis[t]==inf)return false;
	return true;
}
int dfs(int u,int mf){
	int v,flow,x,sum=0;
	if(u==t||!mf)return mf;
	for(int &i=cur[u];i!=-1;i=e[i].next){
		v=e[i].v,flow=e[i].flow;
		if(flow&&dis[v]==dis[u]+1){
			x=dfs(v,min(mf,flow));
			e[i].flow-=x;
			e[i^1].flow+=x;
			sum+=x;
			mf-=x;
			if(!mf)break;
		}
	}
	if(!sum)dis[u]=0;
	return sum;
}
void dinic(){
	while(bfs()){
		for(int i=1;i<=sz;i++){
			cur[i]=head[i];
		}
		ans+=dfs(s,inf);
	}
}
int main(){
	memset(head,-1,sizeof(head));
	scanf("%d%d%d",&r,&c,&d);
	s=++sz,t=++sz;
	int cnt=0,x;
	char ch[N];
	for(int i=1;i<=r;i++){
		scanf("%s",ch+1);
		for(int j=1;j<=c;j++){
			x=ch[j]-'0';
			if(x){
				a[++cnt].p1=++sz,a[cnt].p2=++sz;
				a[cnt].x=i,a[cnt].y=j;
				addedge(a[cnt].p1,a[cnt].p2,x);
				if(i-d<1||i+d>r||j-d<1||j+d>c){
					addedge(a[cnt].p2,t,inf);
				}
				id[i][j]=cnt;
			}
		}
	}
	for(int i=1;i<=cnt;i++){
		for(int j=i+1;j<=cnt;j++){
			if(dist(a[i],a[j])<=d){
				addedge(a[i].p2,a[j].p1,inf);
				addedge(a[j].p2,a[i].p1,inf);
			}
		}
	}
	for(int i=1;i<=r;i++){
		scanf("%s",ch+1);
		for(int j=1;j<=c;j++){
			if(ch[j]=='L'){
				addedge(s,a[id[i][j]].p1,1);
				tot++;
			}
		}
	}
	dinic();
	printf("%d
",tot-ans);
	return 0;
}
原文地址:https://www.cnblogs.com/chezhongyang/p/7745887.html