Floyd演算法之個人見解

難賦深情發表於2020-11-19

Floyd演算法之個人見解

  因為最近有一個演算法作業要交- -,我看了看題目,大致就是帶權值求最短路徑。所以我想到了弗洛伊德演算法,我就去看了看百度,然後做個總結吧。
  假如我們去旅遊,肯定希望少走冤枉路,那麼我們就要知道任何兩個地方最短的距離。
在這裡插入圖片描述
  這四個地方,有八條公路可以到達,請注意這些公路是單向的。我們現在需要求任意兩個城市之間的最短路程,也就是求任意兩個點之間的最短路徑。這個問題這也被稱為“多源最短路徑”問題。
  現在我們需要一個二維陣列來儲存它,可以建立一個4*4矩陣,比如1號城市到2號城市的路程為2,則設e[1][2]的值為2。2號城市無法到達4號城市,則設定e[2][4]的值為∞。另外此處約定一個城市自己是到自己的也是0,例如e[1][1]為0,具體如下。在這裡插入圖片描述
  我們知道,如果要縮短兩點的距離就只有引入中轉點(頂點k)使其路程變短(即a->k->b),有時候可能要兩個中轉點或者更多的點才會讓其路程變得更短,也就是引入k1、k2、k3等等(即a->k1->k2…->k->i…->b),例如上圖,原來4->3路程是12,如果經過1之後變成4->1->3那麼路程就變成了11了(即e[4][1]+e[1][3]=5+6=11)。所以現在將問題轉化成一般情況。

  • 不經過別的中轉點
    在這裡插入圖片描述
  • 經過中轉點1
      只經過中轉點1應該怎麼求呢?只需判斷e[i][1]+e[1][j]是否比e[i][j]要小即可,e[i][j]表示的是從i號頂點到j號頂點之間的路程。e[i][1]+e[1][j]表示的是從i號頂點先到1號頂點,再從1號頂點到j號頂點的路程之和。程式碼實現如下。
for (i = 1; i <= n; i++)
{
     for (j = 1; j <= n; j++)
      {
      	  //迴圈是遍歷整個矩陣,判斷每個點經過1是否會變小
          if (e[i][j] > e[i][1] + e[1][j])
              e[i][j] = e[i][1] + e[1][j];
      }
}

經過1之後,路程表更新為:
在這裡插入圖片描述
  通過上圖我們可以發現,標白的三個地方的路程經過1到其他點的路程變短了。

  • 經過1、2中轉點
      接下來只循序經過1、2會怎麼樣呢?我們需要在只允許經過1號頂點時任意兩點的最短路程的結果下,再判斷如果經過2號頂點是否可以使得i號頂點到j號頂點之間的路程變得更短。即判斷e[i][2]+e[2][j]是否比e[i][j]要小,程式碼實現為如下。
//經過1號頂點
for(i=1;i<=n;i++)
{
	for(j=1;j<=n;j++)
	{
		if (e[i][j] > e[i][1]+e[1][j])  e[i][j]=e[i][1]+e[1][j];
	}
}

//經過2號頂點
for(i=1;i<=n;i++)
{
	for(j=1;j<=n;j++)
	{
		if (e[i][j] > e[i][2]+e[2][j])  e[i][j]=e[i][2]+e[2][j];
	}
}

  在只允許經過1和2號頂點的情況下,任意兩點之間的最短路程更新為:
在這裡插入圖片描述
  我們可以發現之前的4->3經過1(4->1->3)變成了11,現在又經過了2(4->1->2->3)變成了10,

  • 經過1、2、3中轉點
      同理,繼續在只允許經過1、2和3號頂點進行中轉的情況下,求任意兩點之間的最短路程。任意兩點之間的最短路程更新為:
    在這裡插入圖片描述
  • 經過所有中轉點
      最後允許通過所有頂點作為中轉,任意兩點之間最終的最短路程為:
    在這裡插入圖片描述
    整個過程其實可以簡化為幾行程式碼:
for(k=0; k<n ; k++){ //簡單的說就是更新二維矩陣,將任何一個點經過任何一箇中間點之後的路程更新為最短的距離
                            //一句話概括就是:從i號頂點到j號頂點只經過前k號點的最短路程。
        for(i =0; i<n; i++){
        for(j=0; j<n; j++){
            if(e[i][j] > (e[i][k] + e[k][j])){ 
                e[i][j] = e[i][k] + e[k][j];
            }
        }
    }
    }

  上面就是經過所有的中轉點,求的到任意點最短的距離。簡單的說就是從i號頂點到j號頂點只經過前k號點的最短路程。

相關文章