问题描述:售货员要到n个城市去推销商品,已知各城市之间的路程(代价)a[][],试选择一条路,从第一个城市出发经过每个城市一遍,最后回到出发城市所耗费的代价最小。例:
问题分析:分析可知解空间是一棵排列树,每一条从根节点到达叶子结点的路径代表了n个顶点的一种排列。定义x[N]记录可行解。剪枝函数:两个城市之间是否连通,到达当前为止的代价是否已经超过了最优代价,当前城市是否已经走过
#include <iostream>
using namespace std;
#define NoEdge -1 //两点之间无法到达
int n=4; //顶点(城市)数量
int cost=0; //从出发城市到当前位置的代价
int bestc=NoEdge; //最优代价
int bestx[4]; //最优解
int x[4]; //x[i]记录第i个城市的索引
int a[4][4]= //记录城市之间代价,如果两座城市之间不连通则为NoEdge
{
-1,30,6,4,
30,-1,5,10,
6,5,-1,20,
4,10,20,-1
};
bool isHave(int i,int t)
{
for(int j=0; j<t; j++)
if(x[j]==i)return true;
return false;
}
void Backtrack(int t)
{
if(t==n)
{
//最后一个城市和出发城市是否可到达,该条通路的代价是不是最优
if(a[x[n-1]][0]!=NoEdge
&&((cost+a[x[n-1]][0])<bestc||bestc==NoEdge))
{
for(int i=0; i<n; i++)
{
bestx[i]=x[i];
bestc=cost+a[x[n-1]][0];
}
}
}
else
{
for(int i=0; i<n; i++)
{
//当前城市是否已经走过,当前城市与上一座城市之间是否连通
if(!isHave(i,t)&&a[x[t-1]][i]!=NoEdge&&((cost+a[x[t-1]][i])<bestc||bestc==NoEdge))
{
cost+=a[x[t-1]][i];
//cout<<t<<endl;
x[t]=i;
Backtrack(t+1);
cost-=a[x[t-1]][i];
}
}
}
}
int main()
{
x[0]=0; //出发城市固定为第一座城市
Backtrack(1);
for(int i=0; i<n; i++)
cout<<bestx[i]+1<<" ";
cout<<endl;
cout<<bestc<<endl;
}
时间复杂度:O(n^3)