第一次编写,格式写的比较混乱。先把源码上来吧。这个源码是模仿教材上的(本人学生一枚
)。分析过程在下面。
#include
using namespace std;
class Traveling{
private:
friend int TSP(int**,int*,int,int);
void backTrack(int i);
int city;
int* x;//当前旅行策略
int* bestx;//最优旅行策略
int** a;
int current_cost;//当前代价
int bestc;//存放最小代价值
int NoEdge;//不连通的标志,这里设为-1
};
void Traveling::backTrack(int i)
{
if(i==city){
if(a[x[city-1]][x[city]]!=NoEdge &&
a[x[city]][1]!=NoEdge &&
(current_cost+a[x[city-1]][x[city]]+a[x[city]][1]
{
bestc=current_cost+a[x[city-1]][x[city]]+a[x[city]][1];
for(int j=1;j<=city;j++)
bestx[j]=x[j];
}
}else{
for(int j=1;j<=city;j++)
if(a[x[i-1]][x[j]]!=NoEdge &&
(current_cost+a[x[i-1]][x[i]]
{
swap(x[i],x[j]);
current_cost+=a[x[i-1]][x[i]];
backTrack(i+1);
current_cost-=a[x[i-1]][x[i]];
swap(x[i],x[j]);
}
}
}
int TSP(int** a,int* bestPath,int city,int NoEdge)
{
Traveling Y;
Y.x=new int[city+1];
for(int i=1;i<=city;i++)
Y.x[i]=i;
Y.a=a;
Y.city=city;
Y.bestc=NoEdge;
Y.bestx=bestPath;
Y.current_cost=0;
Y.NoEdge=NoEdge;
Y.backTrack(2);
delete[] Y.x;
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
cout<
}
cout<
}
cout<
for(int i=1;i<=city;i++)
{
cout<
}
cout<
return Y.bestc;
}
void main()
{
int **map;
int * bestpath;
map = new int*[5];
for(int i=0;i<5;i++)
{
map[i] = new int[5];
}
int a[5][5]=
{0,1,2,3,4,
1,-1,30,6,4,
2,30,-1,5,10,
3,6,5,-1,20,
4,4,10,20,-1};
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
map[i][j] = a[i][j];
}
}
bestpath = new int[5];
memset(bestpath,0,sizeof(bestpath));
cout<
}
测试数据的临界矩阵:
0
1
2
3
4
1
0
30
6
4
2
30
0
5
10
3
6
5
0
20
4
4
10
20
0
一、回溯法解旅行商问题
(1) 问题重述
某销售员要到若干城市去推销商品,已知各城市之间的路线(或旅费)。他要选定一条从驻地出发,经过每个城市一遍,最后回到驻地的路线(即哈密顿回路),使总的路程(或总旅费)最小。给定一个有n个顶点V={1,2,……,n}的带权图G=(V,E),旅行商问题就是要在图G中找出一条有最小费用的周游路线(哈密顿回路,即经过V中每一个顶点的简单回路)。
(2)
旅行商问题的解空间是一颗排列树。对于排列树的回溯搜索与生成1,2,3,……,n的所有列的递归算法Perm类似。开始时x=[1,2,…,n],则相应的排列树由x[1:n]的所有排列构成。在backTrack函数中算法的主要流程可以归结如下:
① i=n 时,当前扩展结点是排列树的叶节点的父节点。此时算法检测图G是否存在一条从顶点x[n-1]到顶点x[n]的边和一条从顶点x[n]到顶点1的边。如果这两条边都存在,则找到一条回路。此时算法还需要判断这条回路的代价是否优于已找到的当前最优回路的代价。如果是则更新当前解。
② i
(3) 运行结果
旅行策略13241,最小旅行代价25