排列树问题
问题描述:
某售货员要到若干城市去推销商品,已知各城市之间的路程(旅费),他要选定一条从驻地出发,经过每个城市一遍,最后回到驻地的路线,使总的路程(总旅费)最小。
输出结果:
// 旅行员售货问题 回溯法求解
#include <iostream>
using namespace std;
const int N = 4;//图的顶点数
class Traveling
{
friend int TSP(int **a, int n);
private:
void Backtrack(int i);
int n, // 图G的顶点数
*x, // 当前解
*bestx, // 当前最优解
**a, // 图G的领接矩阵
cc, // 当前费用
bestc; // 当前最优值
int NoEdge; // 无边标记
};
void Swap(int &a, int &b);
int TSP(int **a, int n);
int main()
{
cout<<"图的顶点个数 n="<<N<<endl;
int **a=new int*[N+1];
for(int i=0;i<=N;i++)
{
a[i]=new int[N+1];
}
cout<<"图的邻接矩阵为:"<<endl;
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
cin>>a[i][j];
}
cout<<endl;
}
cout<<"最短回路的长为:"<<TSP(a,N)<<endl;
for(int i=0;i<=N;i++)
{
delete []a[i];
}
delete []a;
a=0;
return 0;
}
void Traveling::Backtrack(int i)
{
if (i == n)
{
if (a[x[n-1]][x[n]] != 0 && a[x[n]][1] != 0 &&
(cc + a[x[n-1]][x[n]] + a[x[n]][1] < bestc || bestc == 0))
{
for (int j = 1; j <= n; j++) bestx[j] = x[j];
bestc = cc + a[x[n-1]][x[n]] + a[x[n]][1];
}
}
else
{
for (int j = i; j <= n; j++)
{
// 是否可进入x[j]子树?
if (a[x[i-1]][x[j]] != 0 && (cc + a[x[i-1]][x[i]] < bestc || bestc == 0))
{
// 搜索子树
Swap(x[i], x[j]);
cc += a[x[i-1]][x[i]]; //当前费用累加
Backtrack(i+1); //排列向右扩展,排列树向下一层扩展
cc -= a[x[i-1]][x[i]];
Swap(x[i], x[j]);
}
}
}
}
int TSP(int **a, int n)
{
Traveling Y;
Y.n=n;
Y.x=new int[n+1];
Y.bestx=new int[n+1];
for(int i=1;i<=n;i++)
{
Y.x[i]=i;
}
Y.a=a;
Y.cc=0;
Y.bestc=0;
Y.NoEdge=0;
Y.Backtrack(2);
cout<<"最短回路为:"<<endl;
for(int i=1;i<=n;i++)
{
cout<<Y.bestx[i]<<" --> ";
}
cout<<Y.bestx[1]<<endl;
delete [] Y.x;
Y.x=0;
delete [] Y.bestx;
Y.bestx=0;
return Y.bestc;
}
void Swap(int &a, int &b)
{
int temp=a;
a=b;
b=temp;
}