货郎担问题(TSP问题)

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

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

货郎担问题要从图g的所有周游路线中求取具有最小成本的周游路线,而由始点出发的周游路线一共有(n一1)!条,即等于除始结点外的n一1个结点的排列数,因此货郎担问题是一个排列问题。通过枚举(n一1)!条周游路线,从中找出一条具有最小成本的周游路线的算法,其计算时间显然为o(n!)。

解货郎担问题:核心是动态规划,自底向上的思想。

下面是代码:我还没写出来……

哼哼:弄出来了

 1 public class Main {
 2 
 3     private static int N = 6;          //此例中共有6个点
 4     private static int index = 1;      //货郎担问题 解的时候假定了第一个起始点就是0,所以从1开始
 5     private int x[] = new int[N];      //每个x[index] 存放的是位置为index 的点  比如index=0  x[1] = 2  位于位置1的点是 点2
 6     private static int bestX[] = new int[N];    //最优路径
 7     private int cLength = 0;                     //当前已经加入的点的长度
 8     private static int allLength = Integer.MAX_VALUE;    //总长
 9     private int weight[][] ={ {0,2,8,5,1,8},    
10                                 {3,0,1,8,5,2},
11                                 {6,2,0,3,6,1},
12                                 {88,3,6,0,6,4},
13                                 {7,2,6,1,0,5},
14                                 {6,3,9,1,4,0}};
15 
16     public static void main(String[] args) {
17         Main tsp = new Main();
18         tsp.getTSP(index);
19         System.out.println(allLength);
20         for (int i = 0; i < N; i++) {
21             System.out.print(bestX[i]+"  ");
22         }
23     }
24     private boolean ifExist(int index){                      //判断index这个位置上是否可以放x[index] 这个点
25         int i=0;                                               //已经加入的位置  x[i]才是该位置的点
26         while(i<index){                                        
27             if(x[i]==x[index]){                                //判断当前位置的点是否已经出现了
28                 return false;
29             }
30             i++;
31         }
32         return true;
33     }
34 
35     private void getTSP(int index){
36         if(index==N-1){
37             for(int j=1;j<=N;j++) {
38                 x[index] = Math.floorMod(x[index] + 1, N);         //通过取余弄出一个当前位置的点                                     
39                 if (ifExist(index) && cLength + weight[x[index - 1]][x[index]] + weight[x[index]][x[0]]< allLength) {    //总长= 已加入长度+ 到该点+该点到初始
40                     allLength = cLength + weight[x[index - 1]][x[index]]+weight[x[index]][x[0]];
41                     for (int i = 0; i < N; i++) {
42                         bestX[i] = x[i];
43                     }
44                 }
45             }
46         }else {
47             for (int j = 1; j <= N; j++) {
48                 x[index] = Math.floorMod(x[index] + 1, N);  //给定当前这个位置的点的值
49                 if (ifExist(index) && cLength + weight[x[index - 1]][x[index]] < allLength) {
50                     cLength += weight[x[index - 1]][x[index]];
51                     getTSP(index + 1);
52                     cLength -= weight[x[index - 1]][x[index]];
53                 }
54             }
55         }
56     }
57 
58 }

这是结果:

 

转载于:https://www.cnblogs.com/12344321hh/p/9617428.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值