前往:我自己搭建的博客
题目
题解
此题要求最短路。题中的机场代表点,但有部分点的坐标没有给出,需要运用几何知识求出。此题的存点方式有一定技巧,序号为i的城市的机场下标为4*i,4*i+1,4*i+2,4*i+3,这样可以将城市与机场的编号关联起来。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=500;
const double inf=2000000000;
int n,a,b;
double plane;
bool vis[maxn];
double d[maxn],p[maxn]; //p[i]表示序号为i的城市的铁路单价
struct airport{double x,y;}v[maxn];
inline void get_place() //求出第四个机场的坐标
{
double l1,l2,l3;
for(int i=1;i<=n;i++)
{
l1=sqrt((v[i<<2].x-v[i<<2|1].x)*(v[i<<2].x-v[i<<2|1].x)+(v[i<<2].y-v[i<<2|1].y)*(v[i<<2].y-v[i<<2|1].y));
l2=sqrt((v[i<<2].x-v[i<<2|2].x)*(v[i<<2].x-v[i<<2|2].x)+(v[i<<2].y-v[i<<2|2].y)*(v[i<<2].y-v[i<<2|2].y));
l3=sqrt((v[i<<2|1].x-v[i<<2|2].x)*(v[i<<2|1].x-v[i<<2|2].x)+(v[i<<2|1].y-v[i<<2|2].y)*(v[i<<2|1].y-v[i<<2|2].y));
double mx=-1; int mv; //找出四个机场的一条对角线
if(l1>mx) mx=l1,mv=1;
if(l2>mx) mx=l2,mv=2;
if(l3>mx) mx=l3,mv=3;
if(mv==1) v[i<<2|3].x=v[i<<2].x+v[i<<2|1].x-v[i<<2|2].x,v[i<<2|3].y=v[i<<2].y+v[i<<2|1].y-v[i<<2|2].y;
else if(mv==2) v[i<<2|3].x=v[i<<2].x+v[i<<2|2].x-v[i<<2|1].x,v[i<<2|3].y=v[i<<2].y+v[i<<2|2].y-v[i<<2|1].y;
else v[i<<2|3].x=v[i<<2|1].x+v[i<<2|2].x-v[i<<2].x,v[i<<2|3].y=v[i<<2|1].y+v[i<<2|2].y-v[i<<2].y;
}
}
inline double get_price(int a,int b) //求从机场a->b的直达价格
{
double dist=sqrt((v[a].x-v[b].x)*(v[a].x-v[b].x)+(v[a].y-v[b].y)*(v[a].y-v[b].y));
if(a>>2==b>>2) return dist*p[a>>2];
else return dist*plane;
}
priority_queue<pair<int,int> > q;
inline void dijkstra(int s)
{
memset(vis,0,sizeof(vis));
for(int i=4;i<=(n<<2|3);i++) d[i]=inf;
d[s]=0; q.push(make_pair(0,s));
while(q.size())
{
int x=q.top().second; q.pop();
if(vis[x]) continue; vis[x]=1;
for(int y=4;y<=(n<<2|3);y++)
{
if(x==y) continue;
double w=get_price(x,y);
if(d[y]>d[x]+w)
{
d[y]=d[x]+w;
q.push(make_pair(-d[y],y));
}
}
}
}
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%d%lf%d%d",&n,&plane,&a,&b);
for(int i=1;i<=n;i++) scanf("%lf%lf%lf%lf%lf%lf%lf",&v[i<<2].x,&v[i<<2].y,&v[i<<2|1].x,&v[i<<2|1].y,&v[i<<2|2].x,&v[i<<2|2].y,&p[i]);
get_place(); double ans=inf;
for(int i=a<<2;i<=(a<<2|3);i++) //分别尝试城市a的四个机场
{
dijkstra(i);
for(int j=b<<2;j<=(b<<2|3);j++) //分别尝试城市b的四个机场
{
ans=min(ans,d[j]);
}
}
printf("%.1f\n",ans);
}
return 0;
}