问题:
TSP问题是指旅行家要旅行n个城市,要求各个城市经历且仅经历一次,然后回到出发城市,并要求所走路程最短。
解决思路:
以四个城市为例讲解
假设n个顶点用0~ n-1个数字编号,首先要生成1~ n-1个元素的子集存放在数组sub[] 中, 设数组d[n][2^n-1]存放迭代结果,其中d[ i ][ j ]表示从顶点 i 经过子集sub[]中顶点一次且仅一次,最后回到出发点0的最短路径长度。
城市个数为4,因此,结果矩阵的列数为2^(4-1)=8 。
用二进制表示子集
例如:第6列,标号为5,用二进制表示为101。三位由高到低分别代表元素3,2,1 。该位为1表示该元素在子集中存在,为0表示不存在。所以101表示子集{1,3}。
**正常人类手写填写顺序
**程序输出结果顺序
函数功能简介:
int c[20][20];//城市间距
int d[20][100];//TSP最终结果
int col;//TSP最终结果表的列数
int sub[100];//子集
void setDistance(int num);//创建城市间间距矩阵C
int subContain(int n);//判断元素是否存在于子集
int subGather(int n,int num);
/*
例:将5(二进制101),转化为子集形式
{1,3}存放在集合sub[]中,
并返回集合元素个数length;
*/
int deSub(int k,int j);
/*
例:求集合{1,3}剔除元素3后的子集.
{1,3}用二进制101表示,剔除元素3
相当于将右数第三位置0.
因此,可以将数字1(二进制001),左移2位为100
再做差101-100=001
得到子集{1};
*/
int doTSP(int num);
void showResult(int num);//输出结果
完整代码:
#include <iostream>
using namespace std;
int c[20][20];//城市间距
int d[20][100];//TSP表结果
int col;//TSP表的列数
int sub[100];//子集
//求子集,详细解释见上面
int subGather(int n,int num)
{
int i,length;
length=0;
for(i=1;i<num;i++)
{
if(n&1==1)
sub[length++]=i;
n=n>>1;
}
sub[length]=-1;
return length;
}
//检查元素是否存在于该子集
int subContain(int n)
{
int i=0;
while(sub[i]!=-1)
{
if(sub[i]==n) return 1;
i++;
}
return 0;
}
//创建城市间距矩阵
void setDistance(int num)
{
int i,j;
cout<<"Set distance:\n";
for(i=0;i<num;i++)
{
for(j=0;j<num;j++)
{
if(i==j)
c[i][j]=-1;
else
{
cout<<"Input the distance between City"<<i<<" and City"<<j<<":";
cin>>c[i][j];
}
}
}
cout << "Set completely!" << endl;
}
//详细解释见上面
int deSub(int k,int j)
{
int temp=1;
temp=temp<<(k-1);
return j-temp;
}
//TSP
int doTSP(int num)
{
int i,j;
//计算矩阵d[][]的列数
for(i=0,col=1;i<num-1;i++,col*=2);
//初始化矩阵d[][]第一列
for(i=1;i<num;i++)
d[i][0]=c[i][0];
//填写第2到col-1列内容
int length;
int aaa=1;
while(aaa<num-1)//按照子集元素个数递增的顺序填表
{
for(j=1;j<col;j++)
{
length=subGather(j,num);
if(length==aaa)
{
for(i=1;i<num;i++)
{
if(subContain(i)==0)//元素不存在于子集
{
int md=10000;//最小值
int temp;
int k;
for(k=0;k<length;k++)
{
temp=c[i][sub[k]]+d[sub[k]][deSub(sub[k],j)];
if(temp<md)
md=temp;
}
d[i][j]=md;
}
}
}
}
aaa++;
}
//填写最后一列
int md=10000;//最小值
int temp;
int k;
length=subGather(col-1,num);
for(k=0;k<length;k++)
{
temp=c[0][sub[k]]+d[sub[k]][deSub(sub[k],col-1)];
if(temp<md)
md=temp;
}
d[0][col-1]=md;
return d[0][col-1];
}
//输出结果
void showResult(int num)
{
int i,j;
for(i=0;i<num;i++)
{
for(j=0;j<col;j++)
cout<<d[i][j]<<"\t";
cout<<endl;
}
}
int main()
{
int num;//城市个数
int p_length;//最短路径长度
cout<<"Input the number of cities:";
cin>>num;
setDistance(num);
p_length=doTSP(num);
cout<<"The length of the shortest path is "<<p_length<<endl;
cout<<"TSP table:\n";
showResult(num);
return 0;
}
运行结果:
致谢~