利用回溯法求解旅行售货员问题Python实现

       回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。

       回溯法的基本行为是搜索,搜索过程使用剪枝函数来为了避免无效的搜索。剪枝函数包括两类:1. 使用约束函数,剪去不满足约束条件的路径;2.使用限界函数,剪去不能得到最优解的路径。

       问题的关键在于如何定义问题的解空间,转化成树(即解空间树)。解空间树分为两种:子集树和排列树。两种在算法结构和思路上大体相同。

       一、问题描述

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

       例如,现在有4个城市,其各顶点的路径长度如下所示:

       二、问题分析

       旅行售货员问题(TSP问题)是一个经典的组合优化问题。经典TSP问题可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地。应如何选择行进路线,以使总的行程最短。

       从图论角度看:

       该问题实质是在一个带权完全无向图中,找一个权值最小的Hamilton回路。由于该问题的可行解是所有顶点的全排列,随着顶点数的增加,会产生组合爆炸,它是一个NP完全问题。

       TSP的数学模型为:

       三、实验代码

# 回溯法求解旅行商问题
import math

n = 4
x = [0, 1, 2, 3]
# 定义图的字典形式
G = {
    '1': {'2': 3, '3': 6, '4': 7},
    '2': {'1': 5, '3': 2, '4': 3},
    '3': {'1': 6, '2': 4, '4': 2},
    '4': {'1': 3, '2': 7, '3': 5}
}
# 定义图的数组形式
graph = [
    [0, 3, 6, 7],
    [5, 0, 2, 3],
    [6, 4, 0, 2],
    [3, 7, 5, 0]
]

# bestcost = 1<<32 # 这里只要是一个很大数就行了 无穷其实也可以
bestcost = math.inf  # 直接取无穷好了
nowcost = 0  # 全局变量,现在的花费


def TSP(graph, n, s):
    global nowcost, bestcost
    if (s == n):
        if (graph[x[n - 1]][x[0]] != 0 and (nowcost + graph[x[n - 1]][x[0]] < bestcost)):
            print('best way:', x)
            bestcost = nowcost + graph[x[n - 1]][x[0]]
            print('bestcost', bestcost)

    else:
        for i in range(s, n):

            # 如果下一节点不是自身 而且 求得的值小于目前的最佳值
            if (graph[x[i - 1]][x[i]] != 0 and nowcost + graph[x[i - 1]][x[i]] < bestcost):
                x[i], x[s] = x[s], x[i]  # 交换一下

                nowcost += graph[x[s - 1]][x[s]]  # 将花费加入
                TSP(graph, n, s + 1)
                nowcost -= graph[x[s - 1]][x[s]]  # 回溯上去还需要减去

                x[i], x[s] = x[s], x[i]  # 别忘记交换回来


TSP(graph, n, 1)

       四、实验结果

D:\Miniconda3\python.exe D:/算法分析与设计/实验/实验三/回溯法—旅行售货员问题.py
best way: [0, 1, 2, 3]
bestcost 10

Process finished with exit code 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Small_Teenager

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值