傻瓜学建模-模拟退火算法解决旅行商问题

1.旅行商问题简介
旅行推销员问题(英语:Travelling salesman problem, TSP)是这样一个问题:给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。
在这里插入图片描述


2.解决思路

打过acm的同学应该都知道一般这种问题可以通过状态压缩dp来求解.如果通过模拟退火(相信你已经知道什么是模拟退货)解决它的难点在于如何生成新解

2.1生成新解的方法:

$交换法:随机选取2个点进行交换
在这里插入图片描述

$移位法:随机选取3个点将前2个点之间的点移动到第3个点后
在这里插入图片描述
$倒置法:随机选取2个点将这2个点之间的顺序完全颠倒
在这里插入图片描述
具体方法怎么来的,我也不是很清楚.
通常这3种方法我们可以混着用;
看看代码;

function pathnew=fun1(path)
        n=length(path);%路的长度
        p1=0.33;%第一种方法概率为0.33 第二种为0.33.......
        p2=0.33;
        r=rand(1);
        if r<p1%%交换法
        c1=randi([2 n-1],1);%%随机生成一个 2~n-1的随机数
        c2=randi([2 n-1],1);%%不考虑2段 因为交换起点和终点没有意义
        pathnew=path;
        pathnew(c1)=path(c2);%%交换
        pathnew(c2)=path(c1);
        
        elseif r<p1+p2%移位法
            c1=randi([2 n-1],1);
            c2=randi([2 n-1],1);
            c3=randi([2 n-1],1);
            sort_c=sort([c1 c2 c3]);
            c1=sort_c(1);
            c2=sort_c(2);
            c3=sort_c(3);
            tem1 = path(1:c1-1);
            tem2 = path(c1:c2);
            tem3 = path(c2+1:c3);
            tem4 = path(c3+1:end);
            pathnew = [tem1 tem3 tem2 tem4];       
        else
            c1 = randi([2 n-1],1);  
            c2 = randi([2 n-1],1);  
            if c1 > c2  % 如果c1比c2大,就交换c1和c2的值
            tem = c2;
            c2 = c1;
            c1 = tem;
            end
            tem1 = path(1:c1-1);     
            tem2 = path(c1:c2);
            tem3 = path(c2+1:end);
            pathnew = [tem1 fliplr(tem2) tem3]; 
        end
        
end

生成新解的问题解决了,剩下的问题也就是套模板了

猜你喜欢

转载自blog.csdn.net/jahup/article/details/109025551