旅行商问题(Traveling Saleman Problem,TSP)又译为旅行推销员问题、货郎担问题,简称为TSP问题,是最基本的路线问题,该问题是在寻求单一旅行者由起点出发,通过所有给定的需求点之后,最后再回到原点的最小路径成本。字面上的理解是:有一个推销员,要到n个城市推销商品,他要找出一个包含所有n个城市的具有最短路程的环路。
    解决TSP问题的思想有回溯法、贪心法、动态规划法等。

    如果动态规划法解决TSP问题,可以参考程序代码:

#include<iostream>
#include<cmath> 
#include<iomanip>
using namespace std;

int s;    //为了方面,直接declare 全局变量
int N;//点的个数 
int init_point;
double x[20];    //城市的x坐标
double y[20];    //城市的y坐标
double dp[20][20];//两个城市的距离   一般不超过20个
double **dis;//2^20  表示出发点到S集合是否已经访问过  数组较大 在main函数中动态内存分配
bool visited[20];   //设置某点的坐标是否访问过 在main函数中初始化false


//时间复杂度是(n*2^n*n = n^2*2^n)  空间复杂度是(n*2^n)
double go(int s,int init)    //init 计数
{
	if (init == N)
	{
		return 0;
	}
	if(dis[s][init]!=-1) return dis[s][init];//去重 
	
	double minlen=100000;
	 
	for(int i=0;i<N;i++)   
	{
		if (!visited[i])
		{
			visited[i] = true;
			double temp = dp[s][i] + go(i,init+1);
			if (temp<minlen)
			{
				minlen = temp;
			}
		}
	} 
        dis[s][init] = minlen;
	return dis[s][init];
}
int main()
{
	for (int i = 0;i<N;i++)
	{
		visited[i] = false;
	}
	int test;
	cout<<"Please input the number of test instance:"<<endl;
	cin>>test;
	while(test--)//测试样例数 
	{
		cout<<"Please input the number of the coordinate(less than 20 for some reason!):"<<endl;
		cin>>N;
		for(int i=0;i<N;i++)
		{
			cout<<"Please input the coordinate of the "<<i+1<<"th x[i] and y[i]:";
			cin>>x[i]>>y[i];//读入城市的坐标 
		}
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
			{
				dp[i][j]=sqrt(pow((x[i]-x[j]),2)+pow((y[i]-y[j]),2));
				//计算两个城市i与j的距离  
			}   
			
			int M = static_cast<int>(pow(2.0,N));

			dis = new double*[M];
			for (int i = 0;i<M;i++)
			{
				dis[i] = new double[N];
			}
			for(int i=0;i<pow(2.0,N);i++)
				for(int j=0;j<N;j++)
					dis[i][j]=-1;//去重数组初始化  

			init_point=0;
			s=0; 
			         
			double distance=go(s,init_point);
			cout<<fixed<<setprecision(2)<<distance<<endl;
			 
			//用完之后记得delete 防止内存泄漏
			for (int i = 0;i<M;i++)
			{
				delete [] dis[i];
			}
			delete [] dis;
	}      
	return 0;
} 

运行结果:


如果直接用递归的方法解决,不去冗余,TSP问题的时间复杂度是O(n!)。优化之后的空间复杂度为O(n*2^n),共对应n*2^n个状态,每个状态循环n次,故时间复杂度为O(n*2^n)*O(n)。


对于动态规划问题的一些感想,动态规划算法,一般采用三部曲:首先,暴力法写出状态转移方程,即递归法;接着,找到冗余;最后,就是去掉冗余,开辟数组来保存计算的中间结果,(例如上面开辟的数组dp[M][N],其中M= 2^N ,至于开辟的大小,对于每个城市有访问和为访问过两种状态)也就是空间换时间。