题目描述
又到暑假了,住在城市 A 的 Car 想和朋友一起去城市旅游。
她知道每个城市都有 4 个飞机场,分别位于一个矩形的 4 个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第 i 个城市中高速铁路了的单位里程价格为
T
i
T_i
Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为 t。
那么 Car 应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
找出一条从城市 A 到 B 的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入格式
第一行为一个正整数 n,表示有 n 组测试数据。
每组的第一行有 4 个正整数 s,t,A,B。
S 表示城市的个数,t 表示飞机单位里程的价格,A,B 分别为城市A,B 的序号。
接下来有 S 行,其中第 i 行均有 7 个正整数
x
i
1
,
y
i
1
,
x
i
2
,
y
i
2
,
x
i
3
,
y
i
3
,
T
i
x_{i1},y_{i1},x_{i2},y_{i2},x_{i3},y_{i3},T_i
xi1,yi1,xi2,yi2,xi3,yi3,Ti ,这当中的
(
x
i
1
,
y
i
1
)
,
(
x
i
2
,
y
i
2
)
,
(
x
i
3
,
y
i
3
)
(x_{i1},y_{i1}),(x_{i2},y_{i2}),(x_{i3},y_{i3})
(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第 i 个城市中任意 3 个机场的坐标,
T
i
T_i
Ti为第 i 个城市高速铁路单位里程的价格。
输出格式
共有 n 行,每行 1 个数据对应测试数据。
保留一位小数。
解题思路
我们把每个城市看成4个点,简单的spfa就好了。
对于每一次测试,都可以共用三个数组,一个是用来记录各个点的坐标的数组,一个是记录点与点之间距离的数组,还有一个是记录城市四个点之间高速的里程费用,我看到一些人还要memset,但是如果相同位置两次测试都要用到,那么后一次测试就会覆盖,如果用不到,那也不会对后一次测试造成影响。
Talking is cheap,show you my code.
代码
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<iomanip>
using namespace std;
double map[401][401];
int point[401][2];
int T[101];
int n;
void get_point(int j) {
int x1 = point[j][0];
int y1 = point[j][1];
int x2 = point[j + 1][0];
int y2 = point[j + 1][1];
int x3 = point[j + 2][0];
int y3 = point[j + 2][1];
int len12 = (x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2);
int len23 = (x2 - x3)*(x2 - x3) + (y2 - y3)*(y2 - y3);
int len13 = (x1 - x3)*(x1 - x3) + (y1 - y3)*(y1 - y3);
if (len12 == (len23 + len13)) {
point[j + 3][0] = x1 + x2 - x3;
point[j + 3][1] = y1 + y2 - y3;
return;
}
if (len23 == (len12 + len13)) {
point[j + 3][0] = x2 + x3 - x1;
point[j + 3][1] = y2 + y3 - y1;
return;
}
if (len13 == (len12 + len23)) {
point[j + 3][0] = x1 + x3 - x2;
point[j + 3][1] = y1 + y3 - y2;
return;
}
}
void init(int s,int t) {
for (int j = 0;j < s;j++) {
for (int k = 0;k < s;k++) {
if (j < k) {
map[k][j] = 0;
}
if (!(map[k][j])) {
if (j != k) {
double len = sqrt(pow(point[j][0] - point[k][0], 2) + pow(point[j][1] - point[k][1], 2));
if ((j / 4) == (k / 4)) {
len *= T[j / 4];
}
else {
len *= t;
}
map[j][k] = len;
}
}
else {
map[j][k] = map[k][j];
}
}
}
}
double spfa(int a, int b, int s) {
double dis[401];
bool use[401];
for (int i = 0;i < s;i++) {
dis[i] = 99999999.9999;
use[i] = false;
}
dis[a] = 0;
use[a] = true;
queue<int> q;
q.push(a);
while (!q.empty()) {
int x = q.front();
q.pop();
use[x] = 0;
for (int i = 1;i < s;i++) {
if (i == x) {
continue;
}
if ((dis[x] + map[x][i]) < dis[i]) {
dis[i] = dis[x] + map[x][i];
if (!use[i]) {
use[i] = 1;
q.push(i);
}
}
}
}
return dis[b];
}
void test_spfa(int a,int b,int s) {
double ans = 999999;
for (int i = 0;i < 4;i++) {
for (int j = 0;j < 4;j++) {
ans = min(ans, spfa(4 * a + i, 4 * b + j, s));
}
}
cout << std::fixed << std::setprecision(1) << ans << endl;
}
void test() {
int s, t, a, b;
cin >> s >> t >> a >> b;
a--;
b--;
for (int j = 0;j < 4 * s;j += 4) {
cin >> point[j][0] >> point[j][1] >> point[j + 1][0] >> point[j + 1][1] >> point[j + 2][0] >> point[j + 2][1] >> T[j / 4];
get_point(j);
}
init(4 * s, t);
test_spfa(a, b, 4 * s);
}
int main() {
cin >> n;
while (n--) {
test();
}
return 0;
}