Car的旅游路线
题目描述
又到暑假了,住在城市 A 的 Car 想和朋友一起去城市旅游。
她知道每个城市都有 4 个飞机场,分别位于一个矩形的 4 个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第 i 个城市中高速铁路了的单位里程价格为 Ti ,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为 t。
图例(从上而下) 机场 高速铁路 飞机航线
注意:图中并没有标出所有的铁路与航线。
那么 Car 应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
找出一条从城市 A 到 B 的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入格式
第一行为一个正整数 n,表示有 n 组测试数据。
每组的第一行有 4 个正整数 s,t ,A ,B。
S 表示城市的个数,t 表示飞机单位里程的价格,A,B 分别为城市A,B 的序号。
接下来有 S 行,其中第 i 行均有 7 个正整数xi1、yi1、xi2、yi2、xi3、yi3、Ti。这当中的 (xi1, yi1)、(xi2, yi2)、(xi3, yi3)分别是第 i 个城市中任意 3 个机场的坐标,Ti 为第 i 个城市高速铁路单位里程的价格。
输出格式
共有 n 行,每行 1 个数据对应测试数据。
保留一位小数。
输入数据
1
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3
输出数据
47.5
数据范围
对于 100% 的数据,1≤n≤10,1≤S≤100,1≤A,B≤S
主要问题
1、根据输入可知,仅给出一个城市三座机场的坐标,第四个机场需要自行求出。
2、求出从起始城市到目的城市的最小花费,可以将每一段路程的距离*费用当做权重,找出最短路即可。
3、路径有两种,一种是两个机场属于同一座城市,只能通过高速铁路。一种是不同城市的机场之间的路径,只能通过飞机航线。
基本思路
1、对于第一个问题,可以通过平行四边形的对角线的交点即为中点来求出第四个机场的坐标。
假设A、B、C为已知的三个机场的坐标。
D为需要求出的第四个机场
可以根据:
求出D的坐标。
如何判断哪一个点是B点,可以通过直角三角形的勾股定理判断。
2、建图时,构建所有的机场两两之间的路径,对于同一个城市的机场与不同城市的机场之间使用不同的单价计算。
3、鉴于该题数据规模不大,可以直接采用最简单的Floyd算法遍历所有两两机场之间的最小花费。最后根据给出的起始城市和目的城市,找出其中哪两个机场作为起点和终点费用最小。
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 100 + 10;
struct node {
int x,y;
int city;
};
struct city {
int T;
};
inline double dis_2(node u1, node u2) {
return (((u1.x - u2.x) * (u1.x - u2.x)) + ((u1.y - u2.y) * (u1.y - u2.y)));
}
inline double dis(node u1, node u2) {
return sqrt(((u1.x - u2.x) * (u1.x - u2.x)) + ((u1.y - u2.y) * (u1.y - u2.y)));
}
node getNode(node u[]) {
//得到第四个机场坐标
node d1, d2, j, x;
if (dis_2(u[1], u[2]) + dis_2(u[1], u[3]) == dis_2(u[2], u[3]))
d1 = u[2], d2 = u[3], j = u[1];
else if (dis_2(u[1], u[2]) + dis_2(u[2], u[3]) == dis_2(u[1], u[3]))
d1 = u[1], d2 = u[3], j = u[2];
else d1 = u[1], d2 = u[2], j = u[3];
x.x = d1.x + d2.x - j.x;
x.y = d1.y + d2.y - j.y;
return x;
}
int main() {
int n;
scanf("%d", &n);
while (n--) {
city c[maxn];
node nod[maxn * 4];
double d[4 * maxn][4 * maxn];
int s, t, A, B;
scanf("%d%d%d%d", &s, &t, &A, &B);
for (int i = 1; i <= s; i++) {
struct node u[5];
for (int j = 1; j <= 3; j++) {
scanf("%d%d", &u[j].x, &u[j].y);
u[j].city = i;
nod[(i - 1) * 4 + j] = u[j];
}
u[4] = getNode(u); // 得到第四个机场坐标
u[4].city = i;
nod[i * 4] = u[4];
scanf("%d", &c[i].T);
}
memset(d, 0, sizeof(d));
for (int i = 1; i <= 4 * s; i++)
for (int j = 1; j <= 4 * s; j++)
if (nod[i].city == nod[j].city) // 同一个城市
d[i][j] = dis(nod[i], nod[j]) * c[nod[i].city].T;
else // 不同城市
d[i][j] = dis(nod[i], nod[j]) * t;
// Floyd找最短路
for (int i = 1; i <= s * 4; i++)
for (int j = 1; j <= s * 4; j++)
for (int k = 1; k <= s * 4; k++)
d[j][k] = min(d[j][k], d[j][i] + d[i][k]);
double ans = INF;
//遍历起始与目的城市的所有机场,找最小
for (int i = 1; i <= 4; i++)
for (int j = 1; j <= 4; j++)
ans = min(d[(A - 1) * 4 + i][(B - 1) * 4 + j], ans);
printf("%.1lf\n", ans);
}
return 0;
}