刻苦努力的奋斗,终于有了学习成果,虽然写出的仅仅是非常拙略,功能单一的,简单的小程序代码,但不失为在代码学习的进步。总算是有了含有自己智慧在其中的结晶。其实这段代码能够顺利完成,虽然是独立完成,但终究还是含有侥幸和巧合的成分的。下面的内容将会使读者对这段代码有一个更为深入的了解。

在写出这段代码之前,我可以说是在黑白不分的日子中艰苦奋斗,捞着相关文章就是一通狂读,遇到不解的程序内容就是一顿狂练,功夫不负有心人,在这种近乎疯狂的学习之后,我在MATLAB的学习道路越走越远.……

在学习MATLAB的过程中我在MATLAB论坛中也搜寻着自己能看懂的文章和代码,以便巩固自己的所学,使得境界更进一步,这样才会使得自己对代码的运用更加灵活,不知不觉下载到了一篇有关算法的文章,内容都是很基础的算法,其中有计算速度和加速度的,包括了简单积分法,和简单公式法,而对我能够编写出最短回路程序帮助最大的例题是与计算路径问题相关的几道例题,虽然这几道例题的整体算法非常差劲,我之所以这么说是因为,他的整体编程思想是最简单的穷举法,凡是对程序编写有了解的人都明白何为穷举法,就是将所有可能的方法利用其中的规律全部列举出来,要知道穷举法应用到最短路算法中的话,这耗的不仅仅是时间而是CPU的速度,要是CPU运算速度非常快,那么有多少回路都会很快的列举出来;若是CPU运算速度非常慢那么即便是列举出非常少的路径,也会花费非常要命的时间。这样对于一个非常需要工作效率的工作的话可就恰到好处的扼住了命运的咽喉。许多成败在此一刻的胜负争夺便就此落下帷幕,很是令人不爽。

虽然这些例题本身都有错误,但是撇开他的错误却是有一点非常值得借鉴的地方,就是利用矩阵本身的定位方法作为代码运算的依据,这样既可以算出回路同时也能更方便的表示出回路的路径,真的不知道这个启发对我有着多么巨大的帮助,能够读到这篇文章是一件多么侥幸的事情啊,并且在错误中发现有价值的方法,更是难上加难的巧合,因此我要感谢这篇文档的编写者,不知道他对我有多么巨大的启发。

下面我们便由这些例题作为我的代码讲解的引述好了:

例题一:当推销员从I城出发,经过每个城市一次且仅一次,最后回到I城,问按怎样的路线走,使总的行程路线最短.四个城市间的距离如下表:

I

II

III

IV

I

0

8

5

6

II

6

0

8

5

III

7

9

0

5

IV

9

7

8

0

〔讲评〕

师:该问题可以用枚举法吗?

生:可以,从I出发有3种选择,第二步只有2种选择,最后一步回I城。

师:如何表示每一步的路长呢?

生:设计一个4×4路长矩阵a, a(i,j)表示城i到城j的路长。

解决这个问题的示例代码如下:

a=[0 8 5 6

6 0 8 5

7 9 0 5

9 7 8 0]; %a,路长矩阵

d=999;%设置总路长初值

for i=2:4;

d1=2:4;d1(d1==i)=[];%保证下一步i不被选

for j=d1;

d2=d1;d2(d2==j)=[]; %保证下一步j不被选,此时d2中只有一个数

b=a(1,i)+a(i,j)+a(j,d2)+a(d2,1); %a,计算路长

if b<d

d=b; %保留更短的路径

p=[1 i j d2 1];%p,记录路径

end; end; end;

例题二:如图,线段旁边的数据表路长,箭头表路的方向,求节点 1 到节点9 的最短路.

〔讲评〕

师:如何用数据描述上图?

生:用9×9矩阵a,a(i,j)表节点i,j间的路长

师:a(4,1),a(3,1)等于多少?

生:无穷大。

师:a(1,1),a(2,2) 等于多少?

生:0

师:如何找最短路径?

生:枚举法,很简单!

师:9个点,要算8!=40320次,若20个点,要算19!>1017次,计算机要算瘫了。

通常采用Dijkstra算法,

第一步:设从点i到j的最短路长f(i,j),就是这点i到j的路长a(i,j)。f也是一个 9×9的矩阵。

第二步,寻找“两边之和小于第三边”,即在 (k=1,2,…9)中寻找使d(k)=a(i,k)+f(k,j) 最小的k,对应的d(k)的值,作为“改良”的 点i到j的最短路长f(i,j)

第三步,重复第二步的工作,考虑到最短路径最多8条边,所以,第二步的重复次数不会超过8

此题示例代码如下:

a=[ 0     6     3     1   Inf   Inf   Inf   Inf   Inf

Inf     0   Inf   Inf     1   Inf   Inf   Inf   Inf

Inf     2     0     2   Inf   Inf   Inf   Inf   Inf

Inf   Inf   Inf     0   Inf    10   Inf   Inf   Inf

Inf   Inf   Inf     6     0     4     3     6   10

Inf   Inf   Inf   Inf     10     0     2   Inf   Inf

Inf   Inf   Inf   Inf   Inf   Inf     0     4   Inf

Inf   Inf   Inf   Inf   Inf   Inf   Inf     0   3

Inf   Inf   Inf   Inf     inf   Inf   Inf     inf     0];

%a,路长矩阵

l=9; %节点数

f=a;%f,最短路长矩阵;

n=1;

while n<8 %n,控制循环次数

for i=1:l

for j=1:l

for k=1:l

d(k)=a(i,k)+f(k,j); %寻找“两边之和小于第三边”的点

end

f(i,j)=min(d);

end;end;

n=n+1;

end

%*********以下是寻找最短路径***

for i=1:l

for j=1:l;

m=i;p{i,j}=i;%p{i,j}, p{i,j}:点i到点j的最短路径;

while f(m,j)~=a(m,j)

for k=1:l

if (f(m,j)==a(m,k)+f(k,j))&(k~=m)&(k~=j)

p{i,j}=[p{i,j} k];m=k;

break

end

end

end;

p{i,j}=[p{i,j} j];

end;end;

例题三:

下图为一网络,节点1到节点2的宽带带宽为6兆,节点1到节点3的宽带带宽为2兆,节点2到节点4的宽带带宽为3兆,…节点4到节点6的宽带带宽为2兆,求节点1到节点6的最大网速。

〔讲评]

师:这个问题用Lingo建模,非常简介,但是用Matlab也可以。

解决这种问题往往分两步:

第一步:寻找从节点1到节点6的通道,并算出该通道的最大网速,并计算出该通道中各宽带剩下的带宽容量,例:节点1,3,5,6通道,可获得网速2,节点1到3的容量变为0,节点3到5变为5,节点5到6变为5。

第二步:重复第一步的工作,直到找不到从节点1到节点6的通道为止。

生:如何寻找节点1到节点6的通道呢?

师:通道就是路径,我们可以给容量不为0的宽带定义路长1,只要我们找到从节点1到节点6的最短路长,如果不是无穷大,那么相对应的路径就是一条通道。

此题示例代码如下:

a=[inf  1.3   2.1  0.9  0.7   1.8   2.0  1.5

1.3     inf  0.9   1.8  1.2   2.6   2.3  1.1

2.1    0.9    inf  2.6    1.7   2.5   1.9  1.0

0.9    1.8    2.6   inf    0.7   1.6   1.5  0.9

0.7   1.2   1.7    0.7    inf   0.9    1.1  0.8

1.8   2.6   2.5    1.6    0.9    inf  0.6  1.0

2.0   2.3   1.9    1.5    1.1    0.6   inf  0.5

1.5    1.1    1.0    0.9    0.8    1.0   0.5  inf];

%a:林区间道路长矩阵

l=length(a);

n=1;%n,计算道路条数

f=zeros(l);%f,记录选中的道路

u=1:l;%u:没连通的林区

[r c]=find(a==min(min(a))); %找最短的道

f(r(1),c(1))=1;%f,记录

u(u==r(1))=[];u(u==c(1))=[];

p=[r(1) c(1)];%p:已连通的林区

while n<l-1

a(p,u)=a(p,u)+0.001;%此处加0.001是为了保证下一步找到最短道路所连的两个林区

[r c]=find(a==min(min(a(p,u))));

a(p,u)=a(p,u)-0.001; %还原0.001

f(r(1),c(1))=1;

%以下将c(1)记作已连通的林区

u(u==r(1))=[];

u(u==c(1))=[];

p=[p r(1) c(1)];

n=n+1;end

这三段代码给予人的启发是非常巨大的,最然第二题和第三题的代码需要整合这三道题的所有思路之后才能正确的编写出属于各自例题的代码,因此从三道例题整体上看并没有错误,但是若是一道例题一道例题分开着看的话,相信每一个做过这些例题的人都会知道只有第一道题的运算结果是部分正确的。

我在这里就不再赘述第二题和第三题的正确解法,这不是本文所讨论的关键所在,希望对此感兴趣的读者自己独立完成后两道题的正确求解过程,相信你会有精彩的发现。

之后呢我便根据这些代码所获得的经验总结出了我自己的代码思路,依据分枝定界法,编写出了自己能够独立完成的代码:

a=[0 20 1 11 2
    0 0 9 1 3
    0 0 0 13 8
    0 0 0 0 6
    0 0 0 0 0];

l=length(a)
s1=inf  %标记的非H回路的路程和
zp=inf  %标记的H回路的路程和
n2=1
f=a
f(a==0)=inf
b=zeros(l)
i1=0
while i1<=l-1
    [r c]=find(f==min(min(f)))
    b(r(1),c(1))=f(r(1),c(1))
    f(r(1),c(1))=inf
    i1=i1+1
end
f1=f
bz=b

%以上标定五个最小值
[rz cz]=find(b>0)
pathz=[rz cz]
pz=[rz;cz]
p2z=zeros(2*l,1)
i2z=1
n2z=0
    while i2z<=2*l
        [r2z c2z]=find(pz==pz(i2z,1))
        k1z=size(r2z)
        if k1z(1,1)>2
            p2z(r2z,1)=pz(r2z,1)
            n2z=n2z+1
        end
        i2z=i2z+1
    end
    %----------
if n2z<=2
    HHL=b
    zp=sum(sum(b))
else
    %------------------------
while min(min(f1))~=inf
    if n2>2
        b=snh
    end
%以下计算重复点
    [r1 c1]=find(b>0)
    path1=[r1 c1]
    p1=[r1;c1]
    p2=zeros(2*l,1)
    i2=1
    n2=0
    while i2<=2*l
        [r2 c2]=find(p1==p1(i2,1))
        k1=size(r2)
        if k1(1,1)>2
            p2(r2,1)=p1(r2,1)
            n2=n2+1
        end
        i2=i2+1
    end
    [r3 c3]=find(p2>0)
    p3=zeros(l,2)
    i3=0
    while i3<=n2-1
        if r3(1)<=l
            p3(r3(1),:)=path1(r3(1),:)
        else
            p3(r3(1)-l,:)=path1(r3(1)-l,:)
        end
        r3(1)=[]
        i3=i3+1
    end
    p3(p3==0)=[]
    p3=reshape(p3,n2,2)
    p8=p2
    [r8 c8]=find(p8>0)
    %以上计算重复点
    %以下为在其他矩阵中排除重复
   
    p9=p8
    r9=r8
    i4=1
    while i4<=n2
        f1(p9(r9(1),1),:)=inf
        f1(:,p9(r9(1),1))=inf
        r9(1)=[]
        i4=i4+1
    end

%以上在其他矩阵中排除重复点
    %以下求出排除过相同点的矩阵中的最小值
    [r4 c4]=find(f1==min(min(f1)))
    f1(r4,c4)=inf
    b1=b
    b1(r4,c4)=a(r4,c4)
    %以上求出排除过相同点的矩阵中的最小值
    %以下开始循环替换并进行标记
    i5=1
    p4=p3
    while i5<=n2    %替换的次数基于重复的点数
        b1=b
        b1(r4(1),c4(1))=a(r4(1),c4(1))
        b1(p4(1,1),p4(1,2))=0
        p4(1,:)=[]
        %以下判断本次循环替换中的路径是否为H回路
        [r5 c5]=find(b1>0)
        p5=[r5;c5]
        i6=1
        n6=0
        while i6<=2*l
            [r6 c6]=find(p5==p5(i6,1))
            k6=size(r6)
            if k6(1,1)>2
                n6=n6+1
            end
            i6=i6+1
        end
        if n6>2
            if sum(sum(b1))<s1
                snh=[]
                s1=sum(sum(b1))
                snh=b1
            end
        else
            if sum(sum(b1))<zp
                HHL=[]
                zp=sum(sum(b1))
                HHL=b1
            end
        end
        i5=i5+1
    end
end
end
%以下为结果整理
[rs cs]=find(HHL>0)
minpaths=[rs cs]
journeys=zp

今天对这篇文章的编写算是简单的有了一个比较小的总结,相信明天的总结会更精彩。

分枝定界法求哈密尔登回路问题的由表及里相关推荐

  1. 【数学建模入门】整数规划求最优解|分枝定界法求最优解

    文章目录 整数规划 分枝定届法 `intprog` `branchbound` 整数规划 intprog() function [x,fval,status] = intprog(f,A,B,I,Ae ...

  2. Python整数规划—分枝定界法

    分枝定界法可用于解纯整数或混合的整数规划问题.在本世纪六十年代初由 Land Doig 和 Dakin 等人提出的.由于这方法灵活且便于用计算机求解,所以现在它已是解 整数规划的重要方法.目前已成功地 ...

  3. Python 实现整数线性规划:分枝定界法(Branch and Bound)

    今天做作业,要实现整数线性规划的分枝定界法算法.找了一些网上的博客,发现都很屎,感觉自己写的这个比较清楚.规范,所以在此记录.如有错误,请指正. from scipy.optimize import ...

  4. 分枝定界法解0/1背包问题

    分枝定界法解0/1背包问题 关键词:分支定界.0-1背包 分枝定界法简介 分枝定界法按照树形结构来组织解空间,展开节点后,有两种策略: 策略一.把节点加入 FIFO 队列当中: 策略二.把节点加入到堆 ...

  5. 分枝定界法的一般步骤

    分枝定界法的一般步骤 设有最大化的整数规划问题A ,与它相对应的松弛问题为 B. (1)先不考虑原问题的整数约束,求解相应的松弛问题.用图解法或单纯形法求得最优解,记为 . (2)若求得的最优解 刚好 ...

  6. python混合整数线性规划_Python 实现整数线性规划:分枝定界法(Branch and Bound)...

    今天做作业,要实现整数线性规划的分枝定界法算法.找了一些网上的博客,发现都很屎,感觉自己写的这个比较清楚.规范,所以在此记录.如有错误,请指正. from scipy.optimize import ...

  7. 分支定界 matlab,使用MATLAB实现分枝定界法求解整数规划的详细资料说明

    分支定界法是一种求解离散最优化问题的计算分析方法.它是由Land Doig和Dakin等人在20世纪60年代初提出的.分支定界法可求纯整数或混合整数线性规划问题,求解方法由分支和定界组成." ...

  8. 整数规划之分枝定界法

    整数规划之分枝界定法 引子: 题目分析: 这个整数规划问题相当于是在简单的线性规划问题上增加了决策变量为整数的限制条件.如果没有这个限制条件,那我们用linprog函数很容易解决如下 >> ...

  9. 算法分支定界法C语言程序,常用算法大全-分枝定界

    任何美好的事情都有结束的时候.现在我们学习的是本书的最后一章.幸运的是,本章用到的大部分概念在前面各章中已作了介绍.类似于回溯法,分枝定界法在搜索解空间时,也经常使用树形结构来组织解空间(常用的树结构 ...

最新文章

  1. 项目管理过程中应注意的问题
  2. Python高级函数
  3. 2019区块链行业指南
  4. mysql命令实践_MySQL:常用命令行
  5. 从 Flink 应用场景出发,了解它的设计思路
  6. 2019 最新计算机技能排名出炉:Python 排第三,第一名是...
  7. JavaScript邮箱验证-正则验证
  8. php如何做支付,php实现银联支付
  9. python安装openpyxl库_Python openpyxl 库
  10. 阅读《视音频编解码技术零基础学习方法-雷霄骅》摘要
  11. 计算机ps论文范文,ps论文范文
  12. Hologres性能调优
  13. 视觉分类任务中,Confusion Matrix (混淆矩阵) 的绘制
  14. Java对文件进行加密解密操作
  15. 幂等和非幂等的关系与区别
  16. 机器学习-聚类PPT
  17. 汇通达港交所上市:市值超240亿港元 阿里与顺为是股东
  18. 解神者x2服务器维护,解神者X2许愿币获取方法一览
  19. hdu-4976-A simple greedy problem.
  20. OpenWRT上安装FreeSWITCH

热门文章

  1. 从0开始部署vue教程
  2. 前端FormData详解
  3. WKWebView 白屏问题
  4. Tomcat启动异常 Failed to read candidate component class 解决办法
  5. 自定义UITableViewCell实现类似iBooks图书列表形式
  6. ZBRUSH 2019有什么新功能
  7. get/post/put/delete请求头说明
  8. Java网络编程UDP编程
  9. 人工智能chatgpt的国内的稳定镜像
  10. 致毕业生:那些年我们错过的“BAT” 1