动态规划---->货郎担问题

货郎担问题

问题描述

货郎担问题也叫旅行商问题,即TSP问题(Traveling Salesman Problem),是数学领域中著名问题之一。

其一般提法为:有n个城市,用1,2,…,n表示,城i,j之间的距离为dij,有一个货郎从城1出发到其他城市一次且仅一次,最后回到城市1,怎样选择行走路线使总路程最短? 

旅行商问题的提法为:假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路经的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。

 

假设周游路线是开始于结点1并终止于结点1 的一条简单路径。每一条周游路线都由一条边〈1,k〉和一条由结点k 到结点1 的路径所组成, 其中k∈V-{1} ; 而这条由结点k 到结点1 的路径通过V-{1 ,k}的每个结点各一次。容易看出, 如果这条周游路线是最优的, 那么这条由k 到1 的路径必定是通过V-{1, k}中所有结点的由k到1的最短路径, 因此最优性原理成立。设g(i,S)是由结点i开始, 通过S中的所有结点, 在结点1终止的一条最短路径长度。g(1,V-{1}) 是一条最优的周游路线长度。于是, 可以得出

g(1,V-{1}) = min{c1k + g( k,V-{1,k})}   2≤k≤ n

一般化可得g(i,S) = min{ cij+ g(j,S-{j}) }

2、例子

 

g(2 ,空) = c21 =  5

g(3,空) = c31 =  6

g(4,空) = c41 =  8

由式g( i, S) = min{cij + g( j, S - {j}) } 得

g(2,{3} ) = c23  + g(3,空) = 15

g(2,{4} ) = 18

g(3,{2} ) = 18

g(3,{4} ) = 20

g(4,{2} ) = 13

g(4,{3} ) = 15

接着,计算在|  S| = 2 且i≠1,1|  S,i| S 情况下的g(  i,S) :

g(2,{3,4} ) =  min{c23 + g( 3,{4}), c24  + g(4,{3} )} = 25

g(3,{2,4} ) =  min{c32 + g( 2,{4}), c34  + g(4,{2} )} = 25

g(4,{2,3} ) =  min{c42 + g( 2,{3}), c43  + g(3,{2} )} = 23

最后,得

g(1,{2,3,4} ) =  min{c12 + g( 2,{3,4}), c13  + g(3,{2,4} ), c14 + g( 4,{2,3}) }= min{35,40,43} = 35

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态规划货郎担问题是指在给定的n个城市之间,求解一条经过每个城市恰好一次的最短路径。这个问题可以使用动态规划算法来解决。具体来说,可以使用一个二维数组g[i][S]来表示从城市i开始,经过集合S中的所有城市,最终回到城市1的最短路径长度。其中,集合S是除了城市1之外的所有城市的集合。根据动态规划的思想,可以先求解子问题,再从子问题的解得到原问题的解。因此,可以按照以下步骤来求解动态规划货郎担问题: . 初始化g[i][S],当S中只有一个城市j时,g[i][{j}]的值为城市i到城市j的距离。 2. 对于集合S中的每个城市j,计算g[i][S]的值。具体来说,可以枚举S中除了j之外的所有城市k,计算g[k][S-{j}]的值,然后加上城市i到城市j的距离,取最小值即可。 3. 最终的答案是g[{2,3,...,n}],即从城市1开始,经过除了城市1之外的所有城市,最终回到城市1的最短路径长度。 下面是动态规划货郎担问题的C++代码实现: ``` #include <iostream> #include <cstring> using namespace std; const int MAXN = 20; const int INF = 0x3f3f3f3f; int n, cost[MAXN][MAXN], g[MAXN][1 << MAXN]; int tsp(int start, int state) { if (state == (1 << n) - 1) { return cost[start][0]; } if (g[start][state] != -1) { return g[start][state]; } int ans = INF; for (int i = 0; i < n; i++) { if ((state & (1 << i)) == 0) { ans = min(ans, cost[start][i] + tsp(i, state | (1 << i))); } } return g[start][state] = ans; } int main() { memset(g, -1, sizeof(g)); cout << "请输入n的值" << endl; cin >> n; int cc[MAXN][MAXN]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cout << "请输入各成本值" << endl; cin >> cc[i][j]; cost[i][j] = cc[i][j]; } } cout << tsp(0, 1) << endl; return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值