日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

847. Shortest Path Visiting All Nodes(三)

發(fā)布時間:2023/12/10 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 847. Shortest Path Visiting All Nodes(三) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

DP
 這道題目還可以用動態(tài)規(guī)劃解決。在圖論中解決最短路徑問題有Dijkstra算法和bellman-ford算法。這道題目也需要用到DP。所以先學(xué)習(xí)一下這兩個算法的思想和區(qū)別。
 兩個算法比較
 Dijstra算法用來解決單源最短路徑問題。具體內(nèi)容看[文章]

算法解決問題適用范圍解決思路松弛對象
Dijkstra算法單源最短路徑權(quán)重是正的圖貪心頂點
bellman-ford算法單源最短路徑圖,不可以有負(fù)權(quán)環(huán)路動態(tài)規(guī)劃

ps:雖然我也不明白為什么叫松弛。只知道是不斷處理,不斷優(yōu)化的對象。
 之所以做比較是想明白這兩個算法有什么區(qū)別。以及第二個算法的思想是怎么應(yīng)用在本題目。
 本題目的DP方案參考鏈接。
 首先使用Floy算法計算任意兩點之間的最短路徑。接著使用遞歸方程dp[i][j] = Math.min(dp[i][j],dp[包含u但是不包含v 的狀態(tài)][u]+dist[u][v])。

public class ShortestPathVisitingAllNodesDP {private int[][] dis = new int[15][15];private int[][] dp =new int[1<<13][13];public int shortestPathLength(int[][] graph) {int N = graph.length;for (int[] row: dis) Arrays.fill(row, N*N);for (int i=0; i<N; i++) {for (int j=0; j<graph[i].length; j++) {int u = i, v = graph[i][j];dis[u][v] = 1;}}floyd(N);return dp(N);}/*** Floy算法:任意兩點之間的最短距離* @param n*/public void floyd(int n) {for(int k=0; k<n; k++)for(int i=0; i<n; i++)for(int j=0; j<n; j++)dis[i][j] = Math.min(dis[i][j], dis[i][k]+dis[k][j]);}private int dp(int n) {for (int[] row: dp) Arrays.fill(row, n*n);for (int i=0; i<n; i++)dp[1<<i][i] = 0;for (int group=1; group<(1<<n); group++)for (int u=0; u<n; u++)for (int v=0; v<n; v++) {int src = 1 << u, dst = 1 << v;//group包含src,但是不包含dstif ((group & src)!=0 && (group & dst)==0 )dp[group|dst][v] = Math.min(dp[group][u] + dis[u][v], dp[group|dst][v]);}int minDis = 0x3f3f3f3f;for (int i=0; i<n; i++)minDis = Math.min(dp[(1<<n)-1][i], minDis);return minDis;}public static void main(String[] args){int[][] graph = new int[4][];graph[0] = new int[]{1,2,3};graph[1] = new int[]{0};graph[2] = new int[]{0};graph[3] = new int[]{0};int r = new ShortestPathVisitingAllNodesDP().shortestPathLength(graph);System.out.println(r);} }

代碼
 
 關(guān)于FLoyd算法的介紹參考文章。
 用二維數(shù)組記錄任意兩點之間的距離。dis[i][j]表示從i節(jié)點到j(luò)節(jié)點的距離。如果這兩點之間有邊,則dis的初始值是邊的權(quán)重,否則是無窮大。
 如果要讓兩點之間(例如a,b)的路程變短,那只能引入第三點(k)。如果a->k->b的距離小于a->b的距離,那就引入k。有時候可能需要引入不止一個節(jié)點,才能找到ab之間的最短路徑:a->k1->k2…->b。每個頂點可能使得另外兩個節(jié)點路程變短。
 第二步,如果允許在所有節(jié)點之間跨越節(jié)點1。如果dis[i][1]+dis[1][j]&lt;dis[i][j]dis[i][1]+dis[1][j]&lt;dis[i][j]dis[i][1]+dis[1][j]<dis[i][j],那么dis[i][j]=dis[i][1]+dis[1][j]dis[i][j]=dis[i][1]+dis[1][j]dis[i][j]=dis[i][1]+dis[1][j]。需要用兩個for循環(huán)實現(xiàn)替換。
 第三步,如果允許在所有節(jié)點之間跨越節(jié)點1、2。如何做呢?我們需要在只允許經(jīng)過1號頂點時任意兩點的最短路程的結(jié)果下,再判斷如果經(jīng)過2號頂點是否可以使得i號頂點到j(luò)號頂點之間的路程變得更短。即判斷e[i][2]+e[2][j]是否比e[i][j]要小。
 第四步,進(jìn)一步計算允許跨越節(jié)點1,2,3…,一直到節(jié)點n。最后的代碼就是:

public void floyd(int n) {for(int k=0; k<n; k++)for(int i=0; i<n; i++)for(int j=0; j<n; j++)dis[i][j] = Math.min(dis[i][j], dis[i][k]+dis[k][j]);}

總結(jié)

以上是生活随笔為你收集整理的847. Shortest Path Visiting All Nodes(三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。