最短路之浇水

思路

牛棚清理很像,求每个喷水装置可以达到的矩形长度(记得提高精度),为图中的两个点,价值记录为1(需要一个),如果半径小于等于(m/2)为无效内容,然后反向建边,价值记录为0,跑一遍spfa即可。

附上代码一份



#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10+10;
int k,n,m,x,y;
int ver[maxn],next[maxn],tot,head[maxn],edge[maxn];             
bool judge(int a,int b){
	if(b<m/2)return 0;
	double xx=3*sqrt((double)(b*b-(m/2)*(m/2)));
	x=(int)-xx+a*3;y=(int)xx+a*3;
	return 1;
}
void add(int x,int y,int z){
	ver[++tot]=y,edge[tot]=z,next[tot]=head[x],head[x]=tot;
}
bool v[maxn];
int dis[maxn];
queue<int>q;
void spfa(){
	memset(dis,0x3f,sizeof(dis));
	memset(v,0,sizeof(v));
	dis[0]=0;
	v[0]=0;
	q.push(0);
	while(!q.empty()){
		int x=q.front();q.pop();
		v[x]=0;
		for(int i=head[x];i;i=next[i]){
			int y=ver[i],z=edge[i];
			if(dis[y]>dis[x]+z){
				dis[y]=dis[x]+z;
				if(!v[y])q.push(y),v[y]=1;
			}
		}
	
	}
	
}
inline int read(){
	int s=0;
	char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&& ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s;
}
int main(){
	k=read();n=read();m=read();
	int a,b;
	for(int i=1;i<=k;i++){
		a=read();b=read();
		if(!judge(a,b))continue;
		if(x<0)x=0;
		if(y>n*3)y=n*3;
		add(x,y,1);
	}
	
	for(int i=3*n;i>0;i--)add(i,i-1,0);
	spfa();
	if(dis[n*3]<1061109567)printf("%d
",dis[3*n]);
	else printf("-1
");
	return 0;
}

原文地址:https://www.cnblogs.com/soda-ma/p/13227088.html