在本章中,我们将借助以下方法解决旅行商问题 动态编程。
问题陈述:
A salesman will start from a parent city and visit all the cities 上 ly 上 ce and return to parent city. He has to do it with least cost possible.
考虑下图,将父城市设为“ a”。
现在,让我们写一个有效的案例,其中推销员只拜访所有城市一次,然后返回原始城市。
一种 -> b-> > d->a
一种 -> d-> > b->a
以下是无效方案:
一种 -> b-> d-> > b-> a
在这里,我们已经访问了“ b” 2次。从上面的有效情况中可以看出,我们需要找到一个哈密顿循环。
由于可能有许多路线/周期,因此我们需要找到一条成本最低的路线。
下面是邻接矩阵的成本。
因此,可以通过3种不同的方法解决此问题:
- 蛮力法
- 动态编程
- 分支定界法
在本教程中,我们将遵循动态编程方法。
因此,我们将在下面的树的帮助下了解DP的方法:
从给定的图中,我们选择“ a”作为源顶点。
因此,我们可以从“ a”转到“ b”,“ c”和“ d”。它可以显示如下:
同样可以从“ b”转到“ d”或“ c”
同样,他可以从“ c”转到“ b”或“ d”
再次从“ d”转到“ b”或“ c”
再次从节点“ c”转到“ c”
再次从节点“ d”转到“ c”
再次从节点“ b”转到“ d”
再次从节点“ d”转到“ b”
再次从节点“ b”转到“ c”
再次从节点“ c”转到“ b”
因此,上图显示了所有可能的路径。您需要再次到达源顶点。因此,我们可以进一步更新树,如下所示:
从最后一条路径开始,我们从下到上,从成本表中更新成本。
所以从“ d”开始到“ a”,它是3
从“ c”到“ a”的成本是2
从“ d”到“ a”的成本为3
从“ b”到“ a”的成本是6
从“ c”到“ a”的成本是2
从“ b”到“ a”的成本是6
同样,我们将上一层并找到总距离:
> d-> a => i.e > d + d-> a=> 7 + 3 = 10
d-> > a => d-> c + > a => 1 + 2 = 3
b-> d-> a => b-> d + d-> a => 14 + 3 = 17
d-> b-> a => d-> b + b-> a => 10 + 6 = 16
b-> > a => b-> c + > a => 11 + 2 = 13
> b-> a => > b + b-> a=> 5 + 6 = 11
更新后的树如下:
现在,我们再上一层,并检查“ b-> > d->a”,因为我们已经计算出“> d->a”,我们只需要将该值添加到最后一条路径即可。在这里,借助DP表,我们将能够高效地做到这一点。
b-> c + (c -> d-> a) = 11 +10 = 21
b-> a + (d -> > a) = 14 +3 = 17
> b + (b -> d-> a) = 5 +17 = 22
> d + (d -> b-> a) = 7 +16 = 23
d-> b + (b -> > a) = 10 +13 = 23
d-> c + (c -> b-> a) = 1 +11 = 12
现在,我们已经在“ b”,“ c”,“ d”的父节点上计算了所有6条路径的值。我们有2个值,我们需要找到2个值中的最小值。
对于节点“ b”,我们有:
b-> > d-> a = 21
b-> d-> > a = 17
这里的分钟是17,乘17。
对于节点“ c”,我们有:
> b-> d-> a = 22
> d-> b-> a = 23
最小为22。取22。
对于节点“ d”,我们有:
d-> b-> > a = 23
d-> > b-> a = 12
拿12
树将是:
现在,我们上一层,并计算最终路径:
一种 -> b + (b -> d-> > a) = 14 + 17 = 31
一种 -> c + (c -> b-> d-> a) = 9 + 22 = 31
一种 -> d + (d -> > b-> a) = 4 + 12 = 16
最小值是16。因此是我们的结果。
因此,如果推销员沿着路径a行驶-> d-> > b->a,他只能访问所有城市一次,并且以最低的费用到达初始城市。
使用C ++实现旅行推销员问题
#include <vector> #include <iostream> #include <limits.h> using namespace std; int tsp(const vector<vector<int>>& cities, int pos, int visited, vector<vector<int>>& state) { if(visited == ((1 << cities.size()) - 1)) return cities[pos][0]; if(state[pos][visited] != INT_MAX) return state[pos][visited]; for(int i = 0; i < cities.size(); ++i) { if(i == pos || (visited & (1 << i))) continue; int distance = cities[pos][i] + tsp(cities, i, visited | (1 << i), state); if(distance < state[pos][visited]) state[pos][visited] = distance; } return state[pos][visited]; } int main() { vector<vector<int>> cities = { { 0, 15, 4, 5 }, { 14, 0, 11, 4 }, { 5, 21, 0, 8 }, { 5, 4, 12, 0 } }; vector<vector<int>> state(cities.size()); for(auto& neighbors : state) neighbors = vector<int>((1 << cities.size()) - 1, INT_MAX); cout << "minimum: " << tsp(cities, 0, 1, state) << endl; return 0; }
输出:
minimum: 25
进一步阅读:
AJ关于DS和算法的权威指南。单击此处以学习算法和数据结构教程的完整列表。 85多个章节可供学习。
该网站上可用的教程列表:
C编程20+章 | C ++编程80+章 |
100多个编码问题 | 数据结构和算法85+章 |
系统设计20+章 | Shell脚本编写12章 |
4g LTE 60+章节 | 最常见的编码问题 |
5G NR 50+章 | Linux系统编程20+章 |