回溯法——旅行商(TSP)问题

问题描述

给定一个n顶点网络(有向或无向),找出一个包含n个顶点且具有最小耗费的换路。任何一个包含网络所有顶点的换路称为一个旅行。旅行商问题(Traveling Salesman Problem,TSP)是要寻找一条耗费最少的旅行。

《回溯法——旅行商(TSP)问题》 
图1 四顶点网络

如图1是一个四顶点无向网络。这个网络的一些旅行:1,2,4,3,1;1,3,2,4,1和1,4,3,2,1。旅行1,2,4,3,1的耗费为66,;旅行1,3,2,4,1的耗费为25;旅行1,4,3,2,1的耗费为55.故1,3,2,4,1是网络中耗费最少的旅行。

算法设计分析

旅行是包含所有顶点的一个循环,所以可以把任意顶点作为起点也是终点,我们选择顶点1作为起点和终点。于是可以用[1,x2…,xn,1]表示一个旅行,那么x2到xn的所有排列构成n顶点旅行商问题的解空间。

《回溯法——旅行商(TSP)问题》 
图2 四顶点网络的解空间树

城市之间的旅行耗费存储在二维数组cost[n][n] 中, bestCostSoFar 表示当前最优旅行,

C++实现

#include<iostream>
using namespace std;
#define N 5

//全局变量
int n = N - 1;
int cost[N][N];  //cost[1:4][1:4] 表示城市之间的旅行耗费,不存在路径则耗费等于-1
int bestTour[N];  //bestTour[1:4] 记录最佳路径
int currentTour[N];  //currentTour[1:4] 记录当前路径
int bestCostSoFar = -1;  //当前最低耗费
int currentCost = 0;  //当前耗费

void rTSP(int currentLevel)
{//回溯递归函数
    if (currentLevel == n)
    {//当前为叶结点的父节点
        if (cost[currentTour[n - 1]][n] != -1 && cost[currentTour[n]][1] != -1 &&
            (bestCostSoFar == -1 || currentCost + cost[currentTour[n - 1]][n] +
                cost[currentTour[n]][1] < bestCostSoFar))
        {//发现最优的旅行
            bestCostSoFar = currentCost + cost[currentTour[n - 1]][n] +
                cost[currentTour[n]][1];
            copy(currentTour + 1, currentTour + n + 1, bestTour + 1);
        }
    }
    else
    {//搜索子树
        for (int j = currentLevel; j <= n; ++j)
            if (cost[currentTour[currentLevel - 1]][currentTour[j]] != -1 &&
                (bestCostSoFar == -1 || currentCost +
                    cost[currentTour[currentLevel - 1]][currentTour[j]] < bestCostSoFar))
            {//子树currentTour[j]可行
                swap(currentTour[currentLevel], currentTour[j]);
                currentCost += cost[currentTour[currentLevel - 1]][currentTour[currentLevel]];
                rTSP(currentLevel + 1);
                currentCost -= cost[currentTour[currentLevel - 1]][currentTour[currentLevel]];
                swap(currentTour[currentLevel], currentTour[j]);
            }
    }
}

void init()
{
    cost[1][1] = -1;
    cost[1][2] = 30;
    cost[1][3] = 6;
    cost[1][4] = 4;

    cost[2][1] = 30;
    cost[2][2] = -1;
    cost[2][3] = 5;
    cost[2][4] = 10;

    cost[3][1] = 6;
    cost[3][2] = 5;
    cost[3][3] = -1;
    cost[3][4] = 20;

    cost[4][1] = 4;
    cost[4][2] = 10;
    cost[4][3] = 20;
    cost[4][4] = -1;
}
void main()
{
    init();

    int i;
    for (i = 1; i <= n; i++)
        currentTour[i] = i;

    rTSP(2);  //起点定为1,从第二层开始 

    cout << "最少的运费为:" << bestCostSoFar << endl;
    cout << "最佳路径为: ";
    for (i = 1; i <= n; i++)
    {
        cout << bestTour[i] << "->";
    }
    cout << bestTour[1] << endl;
}

测试结果:

最少的运费为:25
最佳路径为: 1->3->2->4->1
请按任意键继续. . .
    原文作者:回溯法
    原文地址: https://blog.csdn.net/mind_v/article/details/73861004
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞