访问多点计算最短路线

举例,武汉出发,想去五岳旅游,最后返回武汉,如果全程高铁或动车,怎样依次访问到并费用最低?

我的思路比较简单,首先手动查询票价信息,整理成表格。

然后列出全排列并记录。

最后计算费用,找出最低值并打印

整理出的表格,为简化问题仅考虑高铁动车费用,10000表示不方便(需要多次换乘等)

武汉泰山华山恒山衡山嵩山
武汉0497.5419651.5229312
泰山5060458.5326760.5296.5
华山406.5479.50184593119.5
恒山10000310233010000262.5
衡山229734633100000512.5
嵩山300335139.5247.5497.50

/*
武汉出发,分别访问五岳,全程火车,怎样火车费用最低?最优解是否唯一?
我国的五岳分别是:东岳山东泰山、西岳陕西华山、北岳山西恒山、南岳湖南衡山、中岳河南嵩山。
*/

#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

// 表示目标点
enum dot
{
	wuhan,       // 武汉
	taishan,     // 泰山
	huashan,     // 华山
	hengshan,    // 恒山
	hengshan2,   // 衡山
	songshan     // 嵩山
};

/*
二维数组保存票价信息
0 武汉
1 泰山
2 华山
3 恒山
4 衡山
5 嵩山
*/
double price[6][6] =
{
	{ 0,      497.5,  419,    651.5,  229,    312 },
	{ 506,    0,      458.5,  326,    760.5,  296.5 },
	{ 406.5,  479.5,  0,      184,    593,    119.5 },
	{ 10000,  310,    233,    0,      10000,  262.5 },
	{ 229,    734,    633,    10000,  0,      512.5 },
	{ 300,    335,    139.5,  247.5,  497.5,  0 }
};

// 记录所有排列结果, 0和6默认是0, 7是费用
vector<vector<int>> results;

int total = 0;
void prt(int arr[], int end, vector<int>& v) {
	v.push_back(0);
	for (int i = 0; i <= end; ++i) {
		v.push_back(arr[i]);
	}
	v.push_back(0);
}

// 使用递归全排列
void perm(int arr[], int begin, int end) {
	if (begin == end) {
		vector<int> v;
		prt(arr, end, v);
		results.push_back(v);
		total++;
		return;
	}
	for (int i = begin; i <= end; ++i) {
		swap(arr[begin], arr[i]);  //交换两个元素值
		perm(arr, begin + 1, end);
		swap(arr[begin], arr[i]);
	}
}

int main()
{
	// 排列所有可能并记录
	int arr[5] = { taishan, huashan, hengshan, hengshan2, songshan };
	perm(arr, 0, 4);
	printf("total : %d\n", total);

	// 遍历计算结果
	for (auto& result : results)
	{
		double sum = 0;
		for (int i = 0; i < 6; i++)
		{
			sum += price[result[i]][result[i + 1]];
		}
		result.push_back(sum);
	}

	// 遍历找出最小结果
	int least = 10000;
	for (auto& result : results)
	{
		if (least > result[7])
		{
			least = result[7];
		}
	}

	// 打印最小结果的所有可能
	for (auto& result : results)
	{
		if (least == result[7])
		{
			printf("%d %d %d %d %d %d %d %d\n", result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7]);
			printf("%lf %lf %lf %lf %lf %lf\n", price[result[0]][result[1]], 
				price[result[1]][result[2]],
				price[result[2]][result[3]],
				price[result[3]][result[4]],
				price[result[4]][result[5]],
				price[result[5]][result[6]]);
		}
	}

	return 0;
}

执行结果

total : 120
0 4 5 2 3 1 0 1881
229.000000 512.500000 139.500000 184.000000 310.000000 506.000000

120表示共有120种排列可能性,5!= 120。

0 4 5 2 3 1 0 1881表示路线为武汉,衡山,嵩山,华山,恒山,泰山,武汉,总费用最低为1881,只存在这一个唯一解(当前条件下)。

229.000000 512.500000 139.500000 184.000000 310.000000 506.000000表示上面行程依次的票价。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值