Matlab最短路問題


實驗目的

  掌握動態規划算法和最短路徑求法,利用最短路徑知識結合實際問題建立數學模型。

實驗要求

  實驗步驟要有模型建立,模型求解、結果分析。

實驗內容

  (1)某公司在六個城市C1,C2,C3,C4,C5,C6中都有分公司,從CiCj的直達航班票價由下述矩陣的第i行、第j列元素給出(∞表示無直達航班),該公司想算出一張任意兩個城市之間最廉價路線表,試作出這樣的表來

  (2)求圖5-28中每一結點到其他結點的最短路

  (3)一只狼、一只羊和一筐白菜在河的一岸,一個擺渡人想把它們渡過河去,但是由於他的船很小,每次只能帶走它們之中的一樣,由於明顯的原因,狼和羊或者羊和白菜在一起需要人看守,問擺渡人怎樣把它們渡過河去?

實驗步驟

(1)解:該公司想算出一張任意兩個城市之間最廉價路線表,可把這個路線表抽象成一副帶權的無向圖,於是問題等價於求每對頂點之間最短的問題。本題使用Floyd算法,用MATLAB編程求解

  首先,編寫floyd.m文件,代碼如下,

 1 %Floyd算法——每對頂點間的最短路徑算法
 2 %輸入:帶權鄰接矩陣w(i,j).
 3 %輸出:距離矩陣D(i,j),R(i,j)
 4 function [d,r]=floyd(w)
 5 [m,n]=size(w);
 6 if n~=m
 7     error('輸入的鄰接矩陣行數不等於列數!!!');
 8 end    
 9 %預分配內存空間
10 d=zeros(n,n);
11 r=zeros(n,n);
12 %賦初值
13 for i=1:n
14     for j=1:n
15         d(i,j)=w(i,j);
16         r(i,j)=j;
17     end
18 end
19 k=1;
20 %更新d,r
21 while k<=n
22     for i=1:n
23         for j=1:n
24             if d(i,k)+d(k,j)<d(i,j)
25                 d(i,j)=d(i,k)+d(k,j);
26                 r(i,j)=r(i,k);
27             end
28         end
29     end
30     k=k+1;
31 end
32 end
floyd.m

  求解,

  

  為了直觀看出最廉價的線路表,這里編程輸出,

 1 % DisplayPath.m 打印路徑函數
 2 function DisplayPath(d,r)
 3 % 打印出任意兩點之間的最短路徑 
 4 % route : 路由表 
 5 % start : 起點index
 6 % dest : 終點index
 7 [m,n]=size(r);
 8 if(n~=m)
 9     error('輸入的路徑矩陣有誤!!!');
10 end
11 for i=1:n
12     for j=i:n
13         if i~=j
14             start=i;
15             dest=j;
16            % fprintf('V%d->V%d\t%d$\t\t',i,j,d(i,j));%例題1
17             fprintf('V%d->V%d\t%d\t\t',i,j,d(i,j));
18             while 1
19                 if(r(start, dest) ~= dest)
20                     fprintf('V%s -> ', num2str(start));
21                     start = r(start, dest);
22                 else
23                     fprintf('V%s -> ', num2str(start));
24                     fprintf('V%s\n', num2str(dest));
25                     break;
26                 end
27             end
28         end
29     end
30 end
DisplayPath.m

  運行示例,

  

   所以,任意兩城市之間最廉價的線路表如下:

序號

始(終)

終(始)

線路

票價

1

C1

C2

1→6→2

35

2

C1

C3

1→5→3,1→6→4→3

45

3

C1

C4

1→6→4,1→5→4

35

4

C1

C5

1→5

25

5

C1

C6

1→6

10

6

C2

C3

2→3

15

7

C2

C4

2→4

20

8

C2

C5

2→4→5

30

9

C2

C6

2→6

25

10

C3

C4

3→4

10

11

C3

C5

3→4→5,3→5

20

12

C3

C6

3→4→6

35

13

C4

C5

4→5

10

14

C4

C6

4→6

25

15

C5

C6

5→1→6,5→4→6

35

  (2)解:每一結點到其他結點的最短路,同樣使用Floyd算法,MATLAB求解。解得,

   

  (3)解:設狼:1,菜:2,羊:3,人:4

  方法1

   不安全的組合:1323123;題目要求轉移方案為安全,所以同樣不能出現的組合:24144。已知安全的組合:12341234123

  人的轉移設定可在河中來回(但是只能搭載一樣),

  

   由上述分析可知,因為河中只能出現2位和1位(當且僅當對岸的組合是123時,人才能獨自在河中出現)的組合,第1趟轉移的安全組合:1234;這兩個組合中只有34有人也就是說,第一趟轉移為:

  

  第二趟轉移的關鍵是當人在回航時如果是獨自回來的話,那么對岸的情況就是1323,都是不安全狀態,那么只能在回航時帶回羊(3)了(因為不帶回羊的話,只能帶回剛運過去的,這就徒勞無功了)(有兩種情況):

   ……

  只討論左圖的情況(右圖以此類推),顯然第3趟是把1移過對岸(因為3才運回出發點,並且把1移過去是安全的):

  

   顯然,第4趟轉移是把3轉移過去,從而完美解決題目要求:

  

  綜上所述,安全可行(沒有多余的無用功)的轉移方案有兩個,都是4趟轉移:

  方案1,第一趟:去(羊人),回(人);第二趟:去(狼人),回(羊人);第三趟:去(菜人),回(人);第四趟:去(羊人)。

  方案2,第一趟:去(羊人),回(人);第二趟:去(菜人),回(羊人);第三趟:去(狼人),回(人);第四趟:去(羊人)。

   方法2

   由組合學知識,

  1位組合:1234

  2位組合:121314232434

  3位組合:123124134234

  4位組合:1234

  其中不允許:123132341424;因此共有10個允許狀態,轉移關系狀態圖如下,

   

  問題歸結為求頂點1234到頂點0的最短路,將上圖改畫為下面形式:

  

  由上圖可知,有兩種過河方案且等優,如先將羊帶到對岸,再將狼帶到對岸同時把羊帶回原處,將白菜帶到對岸,最后把羊帶過去。

小結

  在編寫Floyd程序時,筆者在while循環那里的k值的約束寫成了(k<n),運行之后怎么也得不到筆者想要的結果。筆者數次懷疑自己對路徑矩陣是不是理解錯誤了。於是,筆者回看了路徑矩陣的數學知識,后來實在忍不住筆者就開始一點一點地修改。在修改2個語句后,突然覺得,是不是循環的條件除了問題,果然是的。后來筆者編寫了路徑矩陣的輸出,發現並不能把同一路線的所有情況輸出,可看題1的表,是否有更好的輸出算法呢?

 附錄

  【1】最短路問題(1)  zlc

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM