1. 程式人生 > >數學建模方法-Floyd算法

數學建模方法-Floyd算法

之間 floyd算法 三個點 for 代碼 距離 希望 我們 tla

一、引言

  哈嘍大家好,今天要給大家講的是Floyd算法。在那之前,大家還記得我們上一章講的內容嗎,就是那個Dijkstra算法,用來解決從A點到B點的最短路徑問題。我們還給出了Matlab代碼。Floyd算法也是用來處理最短路徑問題的。它的理念跟Dijkstra有點不一樣,但是最終的結果是一樣的。Floyd算法主要是用到了動態規劃的思想。在這裏博主不打算講到很抽象很高深的東西(畢竟博主也不是專業的),僅僅通過比較通俗易懂的方式來給大家講解這個算法的思想(如果有問題大家幫忙指出來哈)。本文的圖片和思想,借用了https://blog.csdn.net/qq_34374664/article/details/52261672的博文

(圖片畫得好好,有誰知道是用什麽軟件畫的嗎,博主也想學一學)。本篇的主要思想來自那篇博文,因此會有很多類似的,但博主還是想以自己的理解來解釋Floyd算法的理念。好了我們開始吧...

二、Floyd算法

技術分享圖片

  首先,大家看上面的圖,暑假,小哼準備去一些城市旅遊。有些城市之間有公路,有些城市之間則沒有。為了節省經費以及方便計劃旅程,小哼希望在出發之前知道任意兩個城市之前的最短路程。我們用1-4來表示4個地點,並用箭頭和箭頭上的數字來表示一個地點到另一個地點的距離(註意,有些路是單向的)。這樣就得到下圖

技術分享圖片

  現在,我們希望能求解出任意兩點的最短路徑及其距離。

  好了,為了求解這個問題,我們先用一個二維的數組A

來存儲我們圖的信息。如下圖(怎麽看這個圖下面解釋)

技術分享圖片

  這個是怎麽數組填寫出來的呢,舉例來講吧,比如1號城市到2號城市的路程為2,則設A(1, 2)的值為2。2號城市無法到達4號城市,則設置A(2, 4)的值為$\infty$。另外此處約定一個城市自己是到自己的也是0,例如A(1, 1)為0。

  現在問題是,如何求解任意兩個點的最短距離。我們可以這樣想,我們假設第$i$點和第$j$點的距離,應該就包括兩種情況:

  1. $i$和$j$之間是直接相連的(即$i \rightarrow j$);

  2. $i$和$j$之間還有其他端點(即$i \rightarrow \cdot \cdot \cdot \rightarrow j$);

  上面兩句話什麽意思呢,我們先看下面這張圖:

技術分享圖片

  我們現在比如說從地點$i$地點$j$,我們可以直接走紅色路線,即$i \rightarrow j$;或者,走經過1(或者2或者經過1和2)的路線。即從地點$i$開始,先經過其他地點,再從其他地點到$j$,即$i \rightarrow \cdot \cdot \cdot \rightarrow j$

  那麽,哪個才是最短距離呢。接下來就是算法的核心和重點了,大家註意啦!!

  當任意兩點之間不允許經過第三個點時,這些城市之間最短路程就是初始路程,如下

技術分享圖片  (1)現在,如果我只允許經過1號頂點,求任意兩點之間的最短路程,該怎麽求呢?

  由於只允許經過1號頂點,那任意兩點的路線不外乎只有兩種,即:

  1. $i \rightarrow 1 \rightarrow j$

  2. $i \rightarrow j$

  要求最短路程,只要比較這兩個路線距離的大小即可。就是:

  即

A(i, j) = min [A(i, j), A(i, 1) + A(1, j)]

  在只允許經過1號頂點的情況下,任意兩點之間的最短路程更新為:

技術分享圖片

  通過上圖我們發現:在只通過1號頂點中轉的情況下,3號頂點到2號頂點(A(3, 2))、4號頂點到2號頂點(A(4, 2))以及4號頂點到3號頂點(A(4, 3))的路程都變短了。

  (2)接下來繼續求在只允許經過1和2號兩個頂點的情況下任意兩點之間的最短路程。如何做呢?

  可以寫出公式:A(i, j ) = A(i, 1) + A(1, 2) + A(2, j)

  根據(1)我們已經求出A(i, 1) + A(1, 2) = min [A(i, 2), A(i, 1) + A(1, 2)]。

  故我們只需要在只允許經過1號頂點時任意兩點的最短路程的結果下,再判斷如果經過2號頂點是否可以使得$i$號頂點到$j$號頂點之間的路程變得更短。

  即

A(i, j) = min [A(i, j), A(i, 2) + A(2, j)]

  在只允許經過1和2號頂點的情況下,任意兩點之間的最短路程更新為:

技術分享圖片

  通過上圖得知,在相比只允許通過1號頂點進行中轉的情況下,這裏允許通過1和2號頂點進行中轉,使得A(1, 3)和A(4, 3)的路程變得更短了。   (3)同理,繼續在只允許經過1、2和3號頂點進行中轉的情況下,求任意兩點之間的最短路程。任意兩點之間的最短路程更新為: 技術分享圖片   (4)最後允許通過所有頂點作為中轉,任意兩點之間最終的最短路程為: 技術分享圖片   這樣就大功告成啦。   整個算法的思想就是:最開始只允許經過1號頂點進行中轉,接下來只允許經過1和2號頂點進行中轉,接下來······,到允許經過1~n號所有頂點進行中轉,求任意兩點之間的最短路程。用一句話概括就是:從i號頂點到j號頂點只經過前k號點的最短路程。大家好好理一理,邏輯比較容易混亂,但看多幾遍應該就好了。 三、 Floyd算法Matlab代碼
function [D, path] = floyd(A)
% [D,PATH] = FLOYD(A)
% returns the distance and path between the start node and the end node.
%
% A: adjcent matrix
%% 初始化
%節點的數量n
D = A;
n = length(D);
path = zeros(n, n);
%% 初始化path
for i = 1: n
    for j = 1: n
        if D(i, j) ~= inf
            path(i, j) = j;
        end
    end
end
%% 記錄最短路徑與最短距離
for k = 1: n
    for i = 1: n
        for j = 1: n
            if D(i, j) > D(i, k) + D(k, j)
                D(i, j) = D(i, k) + D(k, j);
                path(i, j) = path(i, k);
            end
        end
    end
end

數學建模方法-Floyd算法