问题描述
给定一个n顶点网络(有向或无向),找出一个包含n个顶点且具有最小耗费的换路。任何一个包含网络所有顶点的换路称为一个旅行。旅行商问题(Traveling Salesman Problem,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顶点旅行商问题的解空间。
图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
请按任意键继续. . .