一、简介
TSP问题即旅行商问题,经典的TSP可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地。应如何选择行进路线,以使总的行程最短。从图论的角度来看,该问题实质是在一个带权完全无向图中,找一个权值最小的哈密尔顿回路。
旅行商问题有很多种不同的问法,最近做了几个关于TSP的题,下面总结一下。由于大部分TSP问题都是NP-Hard的,因此很难得到什么高效的多项式级别的算法,一般采用的算法都偏向于暴力搜索以及状压DP,这里都采取用状压DP解决。大部分TSP问题所给的地点数目都非常小。
考虑经典的TSP问题,如果采用状压DP,将每个地点访问与否作为二进制1/0压缩,不难得到状态转移方程:
dp[S][i] = min(dp[S][i], dp[S ^ (1 << (i - 1))][k] + dist[k][i])
S代表当前状态,i(从1开始)表示到达当前状态时最后访问的是第i个地点
k为S中所有访问的与i不同的地点。
dist表示两点间最短路。
以及初始化:
DP[S][i] = dist[start][i](S == 1<<(i - 1))
如果初次遇到状压dp,感到陌生的话,就请仔细思考上面式子的含义,这是大部分TSP问题的关键。
二、源代码
%%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all; %清除所有变量
close all; %清图
clc; %清屏
m=50; %蚂蚁个数
Alpha=1; %信息素重要程度参数
Beta=5; %启发式因子重要程度参数
Rho=0.1; %信息素蒸发系数
G_max=200; %最大迭代次数
Q=100; %信息素增加强度系数
C=[1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;...
3238 1229;4196 1044;4312 790;4386 570;3007 1970;2562 1756;...
2788 1491;2381 1676;1332 695;3715 1678;3918 2179;4061 2370;...
3780 2212;3676 2578;4029 2838;4263 2931;3429 1908;3507 2376;...
3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;...
2370 2975]; %31个省会城市坐标
%%%%%%%%%%%%%%%%%%%%%%%%第一步:变量初始化%%%%%%%%%%%%%%%%%%%%%%%%
n=size(C,1); %n表示问题的规模(城市个数)
D=zeros(n,n); %D表示两个城市距离间隔矩阵
for i=1:n
for j=1:n
if i~=j
D(i,j)=((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2)^0.5;
else
D(i,j)=eps;
end
D(j,i)=D(i,j);
end
end
Eta=1./D; %Eta为启发因子,这里设为距离的倒数
Tau=ones(n,n); %Tau为信息素矩阵
Tabu=zeros(m,n); %存储并记录路径的生成
NC=1; %迭代计数器
R_best=zeros(G_max,n); %各代最佳路线
L_best=inf.*ones(G_max,1); %各代最佳路线的长度
figure(1);%优化解
while NC<=G_max
%%%%%%%%%%%%%%%%%%第二步:将m只蚂蚁放到n个城市上%%%%%%%%%%%%%%%%
Randpos=[];
for i=1:(ceil(m/n))
Randpos=[Randpos,randperm(n)];
end
Tabu(:,1)=(Randpos(1,1:m))';
%%%%%第三步:m只蚂蚁按概率函数选择下一座城市,完成各自的周游%%%%%%
for j=2:n
for i=1:m
visited=Tabu(i,1:(j-1)); %已访问的城市
J=zeros(1,(n-j+1)); %待访问的城市
P=J; %待访问城市的选择概率分布
Jc=1;
for k=1:n
if length(find(visited==k))==0
J(Jc)=k;
Jc=Jc+1;
end
end
%%%%%%%%%%%%%%%%%%计算待选城市的概率分布%%%%%%%%%%%%%%%%
for k=1:length(J)
P(k)=(Tau(visited(end),J(k))^Alpha)...
*(Eta(visited(end),J(k))^Beta);
end
P=P/(sum(P));
%%%%%%%%%%%%%%%%按概率原则选取下一个城市%%%%%%%%%%%%%%%%
Pcum=cumsum(P);
Select=find(Pcum>=rand);
to_visit=J(Select(1));
Tabu(i,j)=to_visit;
end
end
三、运行结果
四、备注
完整代码或者代写添加QQ1575304183