【RQNOJ86】智捅馬蜂窩【最短路】
阿新 • • 發佈:2018-11-10
題目大意:
題目連結:http://www.rqnoj.cn/problem/86
一個座標系上有
個點
條邊,有兩種移動方式:
- 經過一條邊從一個點到達另一個點,耗時為這條邊長度
- 從一個點垂直跳下到達正下方的另一個點。耗時為 (注意: 取 )
求從點 到點 的最小時間。
思路:
對於移動方式
,直接利用勾股求出兩點之間的距離,然後建一條雙向邊。
對於移動方式
,就列舉所有的點,判斷他們是否滿足
且
,如果滿足,那麼就在
到
中連一條單向邊
。
然後跑個最短路就可以了。
程式碼:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <queue>
#define N 200
using namespace std;
int n,tot,head[N];
double v,dis[N];
bool vis[N];
struct edge
{
int next,to;
double dis;
}e[N*2];
struct node
{
double x,y;
}a[N];
double ask_dis(double x1,double y1,double x2,double y2) //勾股求距離
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void add1(int from,int to) //移動方式1
{
e[++tot].to=to;
e[tot].dis=ask_dis(a[from].x,a[from].y,a[to].x,a[to].y)/v/1.0;
e[tot].next=head[from];
head[from]=tot;
}
void add2(int from,int to,double dis) //移動方式2
{
e[++tot].to=to;
e[tot].dis=dis;
e[tot].next=head[from];
head[from]=tot;
}
void spfa()
{
for (int i=1;i<=n;i++)
{
dis[i]=1000000000.0;
vis[i]=0;
}
queue<int> q;
q.push(1);
dis[1]=0.0;
vis[1]=1;
while (q.size())
{
int u=q.front();
q.pop();
vis[u]=0;
for (int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if (dis[v]>dis[u]+e[i].dis)
{
dis[v]=dis[u]+e[i].dis;
if (!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
int main()
{
memset(head,-1,sizeof(head));
cin>>n>>v;
int x,y,fa;
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&fa);
a[i].x=(double)x;
a[i].y=(double)y;
add1(i,fa);
add1(fa,i);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (i!=j)
if (a[i].x==a[j].x&&a[i].y>a[j].y)
add2(i,j,sqrt((a[i].y-a[j].y)*2.0/10.0));
spfa();
printf("%0.2lf",dis[n]);
return 0;
}