旅行商问题分析(分支限界法)

一、题目

 

 

 

二、思路

1、dfs

实验要求用多种思路完成,所以一开始就沿用了上一个实验马走棋盘的思路,添加了邻接矩阵来记录有向网的权值。总体思路还是DFS遍历搜索。

过程剪枝

1、因为要求为最短路径,而一般情况总会存在多条可行路径,在判断过程中需要走过每一条路径才能知道该路径的长度,但如果已知一条可行路径的长度,在计算另一条路径的时候,若还未完成巡回但此时路径长度已经大于已知最短可行路径,那么这条路的最终长度就必定大于已知最短路径,此时就可以不必接下去计算当前路径。

2、之前得出的路径长度可以帮助之后的路径进行快速判断,如果我们尽早得出较短的可行路径,之后的工作也会进行得更快,由剪枝1引出剪枝2,每次选择到下一点路径长度最短的点前进,这样就能较快得到较短的可行路径。

 

2、分支限界法

  按照书本上教我们的思路来实现分支限界法,首先对邻接矩阵进行初始化,求出其的最小下界和对应的矩阵,然后以这个矩阵为根节点,开始进行类似二叉树的遍历。

  在这个过程中,需要保持矩阵每行或每列都必须有一个以上的0,还需要一个函数来找出所有行中最小数中最大的。然后下一步就要决定是否走该行距离为0的点,如果选择走,就将点对应的行和列去掉,若不选择该点,则将该点置为无穷大。并比较选与不选情况下的下界变化,选择下界较小的情况继续进行递归处理,直到矩阵消失或剩下全为无穷大的不可到达点。

  遇到问题:根据以上的逻辑,在实际解决过程中,出现了爆栈的情况,通过调试发现程序运行情况和书本上不一样,书本上有一些变化并没有说明清楚,那么就需要重新考虑程序的递归出口解决爆栈问题。

  

 

 

最后根据书上的情况得修改为一共三种递归出口判断:

 

1、  若剩下的全是无穷远或0(默认跳过-1即不存在的)

2、  若剩下全是无穷远

3、  若剩下全是0

若满足以上任意一种判断,可以直接得出当前下界即为最短路径。

 

 

 

三、复杂度分析

以DFS为主要算法,O(e+v)

时间复杂度(V边数+ E顶点数)

实际复杂度比上述要小,因为在实际中并不会完整遍历所有可行路径。

 

分支限界法完成比较匆忙,代码中要多次循环遍历数组,存在诸多冗余,若不急循环,程序需要的步数及为顶点数,当不断的循环判断使得复杂度难以估计。

  

三、实现代码

1、DFS

 1 public class Sell {
 2     static int[][] byGroup;// 邻接矩阵
 3     static int[] visit;// 0表示未访问 1表示访问
 4     static int N;// 点的个数
 5     static int minstep = 10000;// 最小步数
 6 
 7     class ToNode {
 8         int n;// 第n个点
 9         int L; 当前点到第n个点的距离
10 
11         public ToNode(int n, int l) {
12             this.n = n;
13             this.L = l;
14         }
15     }
16 
17     public static Comparator<ToNode> LComparator = new Comparator<ToNode>() {
   // 优先队列的比較方法(到下一点的距离近到远
18         @Override
19         public int compare(ToNode tn1, ToNode tn2) {
20             return tn1.L - tn2.L;
21         }
22     };
23 
24     public void init() {
25         Scanner sc = new Scanner(System.in);
26         System.out.println("please int N:");
27         N = sc.nextInt();
28         byGroup = new int[N][N];
29         visit = new int[N];
30         for (int i = 0; i < N; i++) {
31             for (int j = 0; j < N; j++) {
32                 System.out.println("please int " + i + "-->" + j + " weight:");
33                 byGroup[i][j] = sc.nextInt();
34             }
35         }
36         DFS(0, 0);// 从0点开始
37     }
38 
39     public void DFS(int n, int step) {
40         if (visit[n] != 0 || step >= minstep) {
   // 当前点走过或当前已走长度大于已知最小可行长度
41             return;
42         }
43         if (step !=
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
旅行商问题是一个NP-hard问题,因此需要采用一些高效的算法来解决。其中分支限界法是一种常用的解决TSP问题的算法。 分支限界法的基本思想是:将问题的解空间树划分为多个子树,每个子树代表一个可行解,通过限界函数对每个子树进行枝,从而减少搜索空间,提高搜索效率。具体来说,分支限界法通过不断地分支和限界,逐步缩小搜索空间,最终找到最优解。 下面是旅行商问题分支限界法的Python实现: ```python import numpy as np class Node: def __init__(self, path, bound, cost): self.path = path self.bound = bound self.cost = cost def tsp_branch_bound(graph): n = graph.shape[0] nodes = [] for i in range(n): path = [i] bound = bound_func(graph, path) cost = 0 nodes.append(Node(path, bound, cost)) nodes.sort(key=lambda x: x.bound) best_path = None best_cost = np.inf while nodes: node = nodes.pop(0) if node.bound >= best_cost: continue if len(node.path) == n: cost = node.cost + graph[node.path[-1], node.path[0]] if cost < best_cost: best_cost = cost best_path = node.path + [node.path[0]] else: for i in range(n): if i not in node.path: path = node.path + [i] bound = bound_func(graph, path) cost = node.cost + graph[path[-2], i] nodes.append(Node(path, bound, cost)) nodes.sort(key=lambda x: x.bound) return best_path, best_cost def bound_func(graph, path): n = graph.shape[0] bound = 0 for i in range(n): if i not in path: min_cost = np.min(graph[i, :]) bound += min_cost for i in range(len(path) - 1): bound += graph[path[i], path[i+1]] return bound # 示例 graph = np.array([[0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]]) best_path, best_cost = tsp_branch_bound(graph) print("最短路径为:", best_path) print("最短路径长度为:", best_cost) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值