TSP问题,动态规划法

    TSP问题是指旅行家要旅行n个城市,要求各个城市经历且仅经历一次然后回到出发城市,并要求所走的路程最短。各个城市间的距离可以用代价矩阵来表示。

    假设从顶点i出发,令d(i, V')表示从顶点i出发经过V'中各个顶点一次且仅一次,最后回到出发点i的最短路径长度,开始时,V'=V-{i},于是,TSP问题的动态规划函数为:

d(i,V')=min{cik+d(k,V-{k})}(k∈V')

d(k,{})=cki(k≠i)

    伪代码:

for (i=1; i<n; i++)     //初始化第0列
	d[i][0]=c[i][0]; 
 for (j=1; j<2n-1-1; j++)  
 	for (i=1; i<n; i++)   //依次进行第i次迭代
		if (子集V[j]中不包含i) 
 			对V[j]中的每个元素k,计算[i][j]=min(c[i][k]+d[k][j-1]);
对V[2n-1-1]中的每一个元素k,计算d[0][2n-1-1]=min(c[0][k]+d[k][2n-1-2]);
输出最短路径长度d[0][2n-1-1];

    笔者在写此程序时卡在了如何判断:子集V[j]中不包含i。解决方法是对n个顶点分别用0~n-1的数字编号,按个数为1,2,……,n-1的顺序生成1~n-1个元素的子集存放在数组V[2^n-1]中。这样,在判断时就可以将当前点与数组编号按位与运算(如下图所示),为0则为需要进行计算(这时才能品味按位与运算的美)。


    完整代码:

#include<iostream.h>
#include<math.h>
int main()
{
	int i,j,k,min,brief,n;
	int D[20][20];
	cout<<"顶点个数:";
	cin>>n;
	int b=(int)pow(2,n-1);
  	for(i=0;i<n;i++)
    	for(j=0;j<n;j++)
      		cin>>D[i][j];
  	int ** Route = (int **)calloc(n, sizeof(int *));
  	int ** Mat = (int **)calloc(n, sizeof(int *));
  	for(i=0;i<n;i++)
  	{
    	Route[i] = (int *)calloc(b*b, sizeof(int))+i*b;
    	Mat[i] = (int *)calloc(b*b, sizeof(int))+i*b;
  	}
  	for(i=0;i<b;i++)
   		for(j=0;j<n;j++)
	    {
			Route[j][i] = -1;
   			Mat[j][i] = -1;
	    }
  	for(i=0;i<n;i++)//初始化第0列 
    	Route[i][0] = D[i][0];    
  	for(i=1;i<b-1;i++)
	    for(j=1;j<n;j++)//依次进行第i次迭代 
			if( ((int)pow(2,j-1) & i) == 0)//子集V[j不包含i 
			{
				min=999;
				for(k=1;k<n;k++)
				if( (int)pow(2,k-1) & i )
				{
					brief = D[j][k] + Route[k][i-(int)pow(2,k-1)]; 
					if(brief < min)
					{
						min = brief;
						Route[j][i] = min;
						Mat[j][i] = k;//局部最优决策
					}
				}    
			}
	min=999;
  	for(k=1;k<n;k++)
	{
		brief = D[0][k] + Route[k][b-1 - (int)pow(2,k-1)];
		if(brief < min)
		{
			min = brief;
			Route[0][b-1] = min;//最优解
			Mat[0][b-1] = k;
		}
	}
	cout<<"最短路径长度:"<<Route[0][b-1]<<endl;//最短路径长度
	cout<<"最短路径:"<<"1";
	for(i=b-1,j=0; i>0; )
	{
		j = Mat[j][i];
		i = i - (int)pow(2,j-1);
		cout<<"->"<<j+1;
	}
	cout<<"->1"<<endl;
	for(i=0;i<n;i++)
	{
		for(j=0;j<b;j++)
  			cout<<Route[i][j]<<" ";
		cout<<endl;
	}
	free(Route);
	free(Mat);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37872090/article/details/80328140