1. 程式人生 > >New Game! (最短路)

New Game! (最短路)

題意:給兩條平行的直線,還有n個圓,在直線和圓上走不耗時間,求最短的時間從一條直線到另一條。

思路:這道題就是讓求最短距離,但真沒想到真是用最短路寫的。。。

程式碼中0,1位置存的是兩條直線節點,

#include<bits/stdc++.h>
using namespace std;
#define N 1000+10
int n;
double a,b,c1,c2;
struct nomd 
{
	int to;
	double cost;
 } ;
double ww(double a,double b,double x,double y,double c)
{
	return fabs((a*x+b*y+c)/sqrt(x*x+y*y));
}
double www(double a,double b,double x,double y)
{
	return fabs(sqrt((x-a)*(x-a)+(y-b)*(y-b)));
}
vector<nomd> G[N];
double s[N],ss[N];
double d[N];
double oo[N],pp[N],ii[N];
typedef pair<int ,int >P;
void di(int q)
{
	priority_queue<P,vector<P>,greater<P> > que;
	for(int i=0;i<=n+2;i++)
	d[i]=1000000000;
	d[q]=0;
	que.push(P(0,q));
	while(!que.empty())
	{
		P p=que.top();que.pop();
		int v=p.second;
		if(d[v]<p.first) continue;
		for(int i=0;i<G[v].size();i++)
		{
			nomd e=G[v][i];
			if(d[e.to]>d[v]+e.cost)
			{
				d[e.to]=d[v]+e.cost;
				que.push(P(d[e.to],e.to));
			}
		}
	}
}
int main()
{
	cin>>n>>a>>b>>c1>>c2;
	for(int i=2;i<n+2;i++)
	{
		cin>>ii[i]>>oo[i]>>pp[i];
		if(ww(ii[i],oo[i],a,b,c1)<=pp[i])
		{
			s[i]=1;
		}
		if(ww(ii[i],oo[i],a,b,c2)<=pp[i])
		{
			ss[i]=1;
		}
		for(int j=2;j<i;j++)
		{
			nomd e;
			e.to=i;
			if(s[i]==s[j]&&s[i]==1||ss[i]==ss[j]&&ss[i]==1||www(ii[i],oo[i],ii[j],oo[j])<=pp[i]+pp[j])
			e.cost=0;
			else
			e.cost=www(ii[i],oo[i],ii[j],oo[j])-pp[i]-pp[j];
			G[j].push_back(e);
			e.to=j;
			G[i].push_back(e);
		}
	}
	for(int i=2;i<n+2;i++)
	{
		nomd e;
		e.to=i;
		if(s[i]==1)
		{
			e.cost=0;
		}
		else
		{
			e.cost=ww(ii[i],oo[i],a,b,c1)-pp[i];
		}
		G[0].push_back(e);
		e.to=0;
		G[i].push_back(e);
	}
	for(int i=2;i<n+2;i++)
	{
		nomd e;
		e.to=i;
		if(ss[i]==1)
		{
			e.cost=0;
		}
		else
		{
			e.cost=ww(ii[i],oo[i],a,b,c2)-pp[i];
		}
		G[1].push_back(e);
		e.to=1;
		G[i].push_back(e);
	}
	nomd e;
	e.cost=fabs((c1-c2)/sqrt(a*a+b*b));
	e.to=1;
	G[0].push_back(e);
	e.to=0;
	G[1].push_back(e);
	di(0);
	printf("%.6lf\n",d[1]);
	return 0;
 }