旅行商问题:
问题描述:已知一个由n个城市(顶点)组成的有向网G , n个城市为v1, v2,…, v n , G的邻接矩阵为D=(d ij)nxn , d ij为边< v i, v j>上的权(表示城市v i到v j的耗费)。
一个旅行商从v1开始,巡回访问每个城市一次且仅一次,最后返回v1, 这个旅行商该如何选择旅行线路,使得整个行程耗费最小?
● 分析:
可利用求一般问题的所有解的回溯算法得到解最优化问题的回溯算法。
(1) 该问题是求最短的哈密顿回路。
(2) 用min表示当前最优值,s[1..n]表示当前最优解。
(3) 除了解的约束条件,用如下剪枝条件进一步剪枝:
当前路径长度>=min
(4) 设置一个标记数组tag[1..n]:
tag[i]=1, 顶点i在当前路径上
tag[i]=0, 顶点i不在当前路径上
当一个顶点退出当前路径时,该顶点的标记应复原为0。
● 回溯算法:
算法 TRAVELING_SALESMAN
输入:正整数n和含n个顶点的有向网G的邻接矩阵D。
输出:关于G的旅行商问题的一条最短旅行线路和最小耗费, 若问题无解,则输出no solution。
min=∞
x[1]=1 //用x[1..n]表示当前搜索路径, 从顶点1开始。
len=0 //len表示当前路径的长度
tag[1]=1; tag[2..n]=0 //设顶点标记初值。
salesman( 2 )
if min<∞ then
output (min, s[1..n]) //输出最优值和最优解。
else
output (“no solution”)//输出无解
end if
end TRAVELING_SALESMAN
过程 salesman(k)
//在已得到当前路径x[1..k-1]的情况下,求G的长度<min //的哈密顿回路中最短的一条,若存在,则用该回路更新min //和s[1..n]的值。
for i=2 to n
x[k]=i //试将顶点i作为当前路径上的第k个顶点。
if route(k) then //当前顶点可作为当前路径的下一顶点。
tag[x[k]]=1; //当前顶点加入当前路径。
len=len+D[x[k-1], x[k]]
if k=n then //找到一条新的哈密顿回路。
if len+D[x[k], 1]<min then
min=len+D[x[k], 1]; s[1..n]=x[1..n]
end if
else
if len<min then //不满足剪枝条件
salesman(k+1)
end if
end if
tag[x[k]]=0 //顶点x[k]退出当前路径。
len=len-D[x[k-1], x[k]]
end if
end for
end salesman
过程 route(k)
//判断当前顶点x[k]是否可作为当前路径x[1..k-1]的下一顶点, //是则返回true, 否则返回false。
if (D[x[k-1], x[k]]<∞)and (tag[x[k]]=0)and(k<n or k=n and D[x[k],1] <∞)
then return true
else return false
end route。