洛谷P1027(Car的旅行路线)

洛谷P1027(Car的旅行路线)

题目描述

又到暑假了,住在城市 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值