1.问题描述:一个联通无向图中,求最短路径回路.也就是求出一个最佳序列,并且终点和起点有直接路径.
2.问题分析:
① 约束条件:因为存在着两个结点不直接相连的情况,有些序列一开始就不可能出现.约束函数存在
记录连接情况的二维数组 T[ t - 1 ][ i ] != // t-1表示上一个结点; i表示全部剩余节点
②限界函数:现有距离+上一站到某个分支的距离优于现有最优值. 当最优解是最小值时,它的初值应该设为
当前距离 cn + 新增距离T[ x[t-1] ][ x[i] ] < 一次递归最优解 bestn //如果误写成T[ t - 1 ][ i ],意味着解序列是默认的{0,1,2,3...}
③具有递归问题中的元素全排列性质, 存在代码结构: 一般来说,还要在Backtrack( t + 1 )前存储当前值,以便回溯
Backtrack( t )
{
...
for (int i = t; i < N; i++)
{
swap(i,t); //a[i]表示全部剩余元素, t表示子问题的队首a[t]
Backtrack(t+1);
swap(i,t);
}
}
二.代码实现分为三部分
1.全局变量定义.
①在实际中,"" 用C++自带的常量INT_MAX表示.
②顺便一提,二维vector输出行数:T.size(); 输出每一行列数T[i].size();
2.递归函数
①使用首位为0的方式计算,A[0]表示起点,从A[1]位开始递归
3.初始化/调用递归函数/打印结果 3 in 1
//TSP is short of "Traveling Salesman Problem" ,旅行商问题
const int M4 = 5;
const int INF = INT_MAX;
vector<vector>T1= //一个5*5的二维数组
{
{INF,3,INF,8,9},
{3,INF,3,10,5},
{INF,3,INF,4,3},
{8,10,4,INF,20},
{9,5,3,20,INF}
};
int cn3; //记录当前值
vector cx3(M4, 0); //记录当前序列
int bestn3; //记录一次递归结束后最优值
vector bestx3(M4, 0); //记录一次递归结束后最优策略
void TSPbacktrack(int t) //默认起点是0,t从 1 开始求解
{
//先写终止条件
if (t >= M4 && //遍历队尾元素,到达叶结点
T1[ 0 ][ cx3[M4-1] ]!=INF && //cx3[]已得出一个解序列,如果结点 0 (起点)和cx3[n-1](终点)相通
cn3 + T1[ 0 ][ cx3[M4 - 1] ]起点距离
}
else
{
for (int i = t; i < M4; i++)
{
if (T1[ cx3[ t - 1 ] ][ cx3[ i ] ] != INF && //当前分支中某结点与上一站相通 且
cn3 + T1[ cx3[ t - 1 ] ][ cx3[ i ] ] < bestn3) //现有距离+上一站到某个分支的距离优于现有最优值
{
swap(cx3[i], cx3[t]); //将选中的该结点与子问题的队首交换
cn3 += T1[ cx3[ t - 1] ][ cx3[ t ] ]; //已选中该结点,更新当前值
TSPbacktrack(t + 1); //递归求解N-1子问题
cn3 -= T1[cx3[ t - 1 ] ][ cx3[ t ] ]; //递归完该结点,恢复当前值
/*①*/ swap(cx3[i], cx3[t]); //回溯
}
}
}
}
void TSP()
{
//初始化
cn3 = 0; //当前初始值=0
/*②*/bestn3 = INF; //求最小值,一次递归最优值的初始值=无穷大
for (int i = 0; i < M4; i++)
{
cx3[i] = i; //默认序列是0,1,2,3....
}
//运算
TSPbacktrack(1);//默认起点是点0,从点1开始
//输出结果
cout << "最优旅行顺序: ";
for (int i = 0; i < M4; i++)
{
cout << bestx3[i] << "-";
}cout << "0";
cout << endl;
cout << "最短里程: " << bestn3;
}
三.BUG分析
主要集中在"解序列"和"默认序列"的差异上
Bug①处:原错误语句:
swap(i, t);
修正后:
swap(x[ i ],x[ t ]); //交换的是序列
Bug②处:原错误语句
bestn3 = 0; //当最优值是一个最小值时,它的初值应该=
作者:IronBull_Zhang