举例,武汉出发,想去五岳旅游,最后返回武汉,如果全程高铁或动车,怎样依次访问到并费用最低?
我的思路比较简单,首先手动查询票价信息,整理成表格。
然后列出全排列并记录。
最后计算费用,找出最低值并打印
整理出的表格,为简化问题仅考虑高铁动车费用,10000表示不方便(需要多次换乘等)
武汉 | 泰山 | 华山 | 恒山 | 衡山 | 嵩山 | |
武汉 | 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 |
/*
武汉出发,分别访问五岳,全程火车,怎样火车费用最低?最优解是否唯一?
我国的五岳分别是:东岳山东泰山、西岳陕西华山、北岳山西恒山、南岳湖南衡山、中岳河南嵩山。
*/
#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表示上面行程依次的票价。