005-5算法笔记【回溯】TSP旅行商问题

题目

某售货员要到若干城市去推销商品,已知各城市之间的路程,他要选定一条从驻地出发,经过每个城市一遍,最后回到住地的路线,使总的路程最短。

在这里插入图片描述

分析

该题利用回溯法求解,该解空间为一棵排列树。
我们假设初始的一条路线为x,x中的值为 1,2,3,……,n,表示该路线为由城市1依次经过城市2、3……到n后再回到城市1(当然是假设该路线存在)。如果不存在的话,我们只需改变一下这个排列的排列方式,再进行判断,所以可想而知,我们可以知道该解空间是一棵排列树。


#include <iostream>
#include <fstream>
using namespace std;

int N = 4; //图的顶点数

template <typename T>
inline void Swap(T &a, T &b);

template <typename T>
T TSP(T **a, int n);

template <typename T>
class Traveling
{
private:
    void Backtrack(int i);
    int n,        // 图G的顶点数
        *x,       // 当前解
        *bestx;   // 当前最优解
    T **a,        // 图G的领接矩阵
        cur_cost, // 当前费用
        bestc;    // 当前最优值
    int NoEdge;   // 无边标记
public:
    friend T TSP<T>(T **a, int n);
};

template <typename T>
void Traveling<T>::Backtrack(int i)
{
    if (i == n)
    {
        if (a[x[n - 1]][x[n]] != 0 && a[x[n]][1] != 0 &&
            (cur_cost + a[x[n - 1]][x[n]] + a[x[n]][1] < bestc || bestc == 0))
        {
            for (int j = 1; j <= n; j++)
                bestx[j] = x[j];
            bestc = cur_cost + a[x[n - 1]][x[n]] + a[x[n]][1];
        }
    }
    else
    {
        for (int j = i; j <= n; j++)
        {
            // 是否可进入x[j]子树?
            if (a[x[i - 1]][x[j]] != 0 && (cur_cost + a[x[i - 1]][x[i]] < bestc || bestc == 0))
            {
                // 搜索子树
                Swap(x[i], x[j]);
                cur_cost += a[x[i - 1]][x[i]]; //当前费用累加
                Backtrack(i + 1);              //排列向右扩展,排列树向下一层扩展
                cur_cost -= a[x[i - 1]][x[i]];
                Swap(x[i], x[j]);
            }
        }
    }
}

template <typename T>
T TSP(T **a, int n)
{
    Traveling<T> Y;
    Y.n = n;
    Y.x = new int[n + 1];
    Y.bestx = new int[n + 1];

    for (int i = 1; i <= n; i++)
    {
        Y.x[i] = i;
    }

    Y.a = a;
    Y.cur_cost = 0;
    Y.bestc = 0;

    Y.NoEdge = 0;
    Y.Backtrack(2);

    cout << "最短回路为:" << endl;
    for (int i = 1; i <= n; i++)
    {
        cout << Y.bestx[i] << " --> ";
    }
    cout << Y.bestx[1] << endl;

    delete[] Y.x;
    Y.x = 0;
    delete[] Y.bestx;

    Y.bestx = 0;
    return Y.bestc;
}

template <typename T>
inline void Swap(T &a, T &b)
{
    T temp = a;
    a = b;
    b = temp;
}

int main()
{
    cout << "请输入图的顶点数:";
    cin >> N;

    int **a = new int *[N + 1];
    for (int i = 0; i <= N; i++)
    {
        a[i] = new int[N + 1];
    }

    cout << "图的邻接矩阵为:" << endl;

    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
        {
            cin >> a[i][j];
            // cout<<a[i][j]<<" ";
        }
        cout << endl;
    }
    int len = TSP(a, N);
    cout << "最短回路的长为:" << len << endl;

    for (int i = 0; i <= N; i++)
    {
        delete[] a[i];
    }
    delete[] a;

    a = 0;
    return 0;
}

/*
4
0 30 6 4
30 0 5 10
6 5 0 20
4 10 20 0

最短回路为:
1 --> 3 --> 2 --> 4 --> 1
最短回路的长为:25
*/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蚁群算法可以用来解决TSP问题,其基本思路是将蚂蚁的行走路径表示为待优化问题的可行解,整个蚂蚁群体的所有路径构成待优化问题的解空间。路径较短的蚂蚁释放的信息素量较多,随着时间的推移,较短的路径上累积的信息素浓度逐渐增高,选择该路径的蚂蚁数量也越来越多。最终,整个蚂蚁会在正反馈的作用下集中到最佳的路径上,此时对应的便是待优化问题的最优解。 蚁群算法解决TSP问题的基本步骤如下: 1. 初始化信息素和蚂蚁的位置。 2. 蚂蚁按照一定的策略选择下一个城市,并更新信息素。 3. 计算每只蚂蚁的路径长度,并记录最短路径。 4. 更新信息素,使得路径较短的蚂蚁释放的信息素量较多。 5. 重复步骤2-4,直到满足停止条件。 下面是一个Python实现的例子: ```python import numpy as np # 城市数量 num_cities = 10 # 蚂蚁数量 num_ants = 20 # 信息素重要程度 alpha = 1 # 启发式因子重要程度 beta = 5 # 信息素挥发速度 rho = 0.1 # 初始信息素浓度 tau0 = 1 # 最大迭代次数 max_iter = 100 # 城市坐标 cities = np.random.rand(num_cities, 2) # 计算城市之间的距离 distances = np.zeros((num_cities, num_cities)) for i in range(num_cities): for j in range(num_cities): distances[i][j] = np.sqrt((cities[i][0] - cities[j][0]) ** 2 + (cities[i][1] - cities[j][1]) ** 2) # 初始化信息素 pheromones = np.ones((num_cities, num_cities)) * tau0 # 迭代 for iter in range(max_iter): # 初始化蚂蚁位置 ants = np.zeros((num_ants, num_cities), dtype=int) for i in range(num_ants): ants[i][0] = np.random.randint(num_cities) # 蚂蚁选择下一个城市 for i in range(num_ants): for j in range(1, num_cities): # 计算城市之间的启发式信息 eta = 1.0 / distances[ants[i][j - 1]][:] # 计算城市之间的信息素浓度 tau = pheromones[ants[i][j - 1]][:] # 计算城市之间的转移概率 p = np.power(tau, alpha) * np.power(eta, beta) p[ants[i]] = 0 p = p / np.sum(p) # 选择下一个城市 ants[i][j] = np.random.choice(num_cities, p=p) # 计算每只蚂蚁的路径长度 lengths = np.zeros(num_ants) for i in range(num_ants): for j in range(num_cities - 1): lengths[i] += distances[ants[i][j]][ants[i][j + 1]] lengths[i] += distances[ants[i][num_cities - 1]][ants[i][0]] # 记录最短路径 best_ant = np.argmin(lengths) best_path = ants[best_ant] best_length = lengths[best_ant] # 更新信息素 pheromones *= (1 - rho) for i in range(num_ants): for j in range(num_cities - 1): pheromones[ants[i][j]][ants[i][j + 1]] += 1.0 / lengths[i] pheromones[ants[i][num_cities - 1]][ants[i][0]] += 1.0 / lengths[i] # 输出结果 print("最短路径:", best_path) print("最短路径长度:", best_length) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值