贪心算法解决旅行商问题
TSP问题(Traveling Salesman Problem,旅行商问题),由威廉哈密顿爵士和英国数学家克克曼T.P.Kirkman于19世纪初提出。问题描述如下:
有若干个城市,任何两个城市之间的距离都是确定的,现要求一旅行商从某城市出发必须经过每一个城市且只在一个城市逗留一次,最后回到出发的城市,问如何事先确定一条最短的线路已保证其旅行的费用最少?
下面采用贪心算法来解决旅行商问题。
贪心算法:又称贪婪算法(greedy algorithm),该算法是指:在对问题求解时,总是做出当前情况下的最好选择,否则将来可能会后悔,故名“贪心”。这是一种算法策略,每次选择得到的都是局部最优解。选择的策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
针对TSP问题,使用贪心算法的求解的过程为:
1.从某一个城市开始,每次选择一个城市,直到所有的城市被走完。
2.每次在选择下一个城市的时候,只考虑当前情况,保证迄今为止经过的路径总距离最小。
具体实现:
C++:
#include<iostream>
using namespace std;
int main()
{
int i,j,k,l;
int n;
cin>>n;//初始化城市个数
int S[n];
//用于存储已访问过的城市
int D[n][n];
//用于存储两个城市之间的距离
int sum = 0;
//用于记算已访问过的城市的最小路径长度
int Dtemp;
//保证Dtemp比任意两个城市之间的距离都大(其实在算法描述中更准确的应为无穷大)
int flag;
////最为访问的标志,若被访问过则为1,从未被访问过则为0
//下面初始化城市之间的距离
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>D[i][j];
//初始化城市之间的距离,由自己输入,应注意i==j时D[i][j]=0,且D[i][j]==D[j][i];
}
}
i = 1;//i是至今已访问过的城市
S[0] = 0;
S[0] = 0;
do{
k = 1;Dtemp = 10000;
do{
l = 0;flag = 0;
do{
if(S[l] == k){//判断该城市是否已被访问过,若被访问过,
flag = 1;//则flag为1
break;//跳出循环,不参与距离的比较
}else
l++;
}while(l < i);
if(flag == 0&&D[k][S[i - 1]] < Dtemp){
//D[k][S[i - 1]]表示当前未被访问的城市k与上一个已访问过的城市i-1之间的距离*/
j = k;
//j用于存储已访问过的城市k
Dtemp = D[k][S[i - 1]];
//Dtemp用于暂时存储当前最小路径的值
}
k++;
}while(k < n);
S[i] = j;//将已访问过的城市j存入到S[i]中
i++;
sum += Dtemp;
//求出各城市之间的最短距离,注意:在结束循环时,该旅行商尚未回到原出发的城市
}while(i < n);
sum += D[0][j];
//D[0][j]为旅行商所在的最后一个城市与原出发的城市之间的距离
for(j = 0; j < n; j++){
//输出经过的城市的路径
cout<<j<<"-->";
}
cout<<endl;
cout<<sum<<endl;//输出最短路径的值
return 0;
}
k = 1;Dtemp = 10000;
do{
l = 0;flag = 0;
do{
if(S[l] == k){//判断该城市是否已被访问过,若被访问过,
flag = 1;//则flag为1
break;//跳出循环,不参与距离的比较
}else
l++;
}while(l < i);
if(flag == 0&&D[k][S[i - 1]] < Dtemp){
//D[k][S[i - 1]]表示当前未被访问的城市k与上一个已访问过的城市i-1之间的距离*/
j = k;
//j用于存储已访问过的城市k
Dtemp = D[k][S[i - 1]];
//Dtemp用于暂时存储当前最小路径的值
}
k++;
}while(k < n);
S[i] = j;//将已访问过的城市j存入到S[i]中
i++;
sum += Dtemp;
//求出各城市之间的最短距离,注意:在结束循环时,该旅行商尚未回到原出发的城市
}while(i < n);
sum += D[0][j];
//D[0][j]为旅行商所在的最后一个城市与原出发的城市之间的距离
for(j = 0; j < n; j++){
//输出经过的城市的路径
cout<<j<<"-->";
}
cout<<endl;
cout<<sum<<endl;//输出最短路径的值
return 0;
}