#include<cstdio>
#include<cmath>
#include<iostream>
#define INF 1e20//有下划线的都是宏
#define FOR(i,x) for(int i=1;i<=(x);i++)
#define For(i,x,y) for(int i=(x);i<=(y);i++)
#define pf(x) (x)*(x)
#define far(a,b) sqrt(pf(d[a][0]-d[b][0])+pf(d[a][1]-d[b][1]))
#define MAX(a,b,c) max(a,max(b,c))
#define IF(x,y) if(x==y)
using namespace std;
int d[5001][2],p[1001],c[5001]; //d[a][]表示机场a的坐标, p[x]表示城市x的高速公路价格, c[a]表示机场a所属的城市
int A,B,t,sum; //sum表示城市个数, t为单位路程飞机的价格, A,B分别为起点,终点
double g[5001][5001];
void readin(),cal(int),gz(int* ,int* ,int* ,int*),ycl();
double floyd();
int main(){
int z;
scanf("%d",&z);
while(z--){
readin();ycl();
printf("%.1lf\n",floyd());//可换成四次dijskra,比一次floyd要略快
}
}
void readin(){ //数据读入
scanf("%d%d%d%d",&sum,&t,&A,&B);
FOR(i,sum){ //用宏简化代码
FOR(j,3){
scanf("%d%d",&d[(i-1)*4+j][0],&d[(i-1)*4+j][1]);
c[(i-1)*4+j]=i;
}
cal(i*4); //求该城市第4个机场的坐标
c[i*4]=i;
scanf("%d",&p[i]);
}
sum*=4; //此时sum表示机场的个数
}
void cal(int x){ //向量求坐标
double k1=far(x-2,x-3),k2=far(x-1,x-3),k3=far(x-2,x-1),maxx=MAX(k1,k2,k3);//maxx是已知三点所构成的直角三角形的斜边长
if(maxx==k1)gz(d[x-1],d[x-3],d[x-2],d[x]); //判断直角顶点
else if(maxx==k2)gz(d[x-2],d[x-1],d[x-3],d[x]);
else if(maxx==k3)gz(d[x-3],d[x-2],d[x-1],d[x]);
}
void ycl(){ //预处理两点之间的直接距离
FOR(i,sum)FOR(j,sum)
IF(c[i],c[j]) g[i][j]=far(i,j)*p[c[i]]; //同一城市
else g[i][j]=far(i,j)*t; //不在同一城市
}
double floyd(){
FOR(k,sum) FOR(i,sum) FOR(j,sum) //floyd,时间复杂度o(n^3),空间复杂度o(n^2),均劣于dijskra
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
double mina=INF;
For(i,(A-1)*4+1,A*4) For(j,(B-1)*4+1,B*4)
mina=min(mina,g[i][j]); //起点有四个,终点有四个,枚举求最短的一条路
return mina;
}
void gz(int*a,int*b1,int*b2,int*x){x[0]=b1[0]+b2[0]-a[0],x[1]=b1[1]+b2[1]-a[1];}//计算第四点(第四个机场)的坐标
car的旅行路线(floyd算法)
最新推荐文章于 2024-07-02 15:26:42 发布