在圖的有關知識中已經了解了dag就是有向無環圖,其中計算最長路(關鍵路徑)的做法非常複雜,這裡介紹更簡單的方法。
求整個dag的最長路徑(即不固定起點和終點)
固定終點,求dag的最長路徑。
給定乙個有向無環圖,怎樣求解整個圖的所有路徑中權值之和最大的那條。
令dp[i]表示從i號頂點出發能獲得的最長路徑長度,這樣所有dp[i]的最大值就是整個dag的最長路徑長度。
如何求解dp陣列,發現dp[i]表示從i號頂點出發能獲得的最長路徑長度,如果從i號頂點出發能到達頂點j1、j2、····、jk,而dp[j1],dp[j2],····,dp[jk]都已知,那麼就有:
dp[i] = max
顯然需要按照逆拓撲序列的順序來求解dp陣列,或者使用遞迴;其中用鄰接矩陣來儲存圖:
intdp(
int i)
}return dp[i]
;//返回計算完畢的dp[i]
}
在具體實現時,對整個dp陣列進行初始化為0。 這樣如果遇到出度為0的結點會自動返回dp[i]= 0,而如果出度不是0的頂點則會遞迴求解。
如何知道最長路徑具體是哪條呢?
可以開乙個int型choice陣列記錄最長路徑上的頂點的後繼頂點,使用迭代即可獲得每個的後繼頂點。如果最終可能有多條最長路徑,把choice陣列改為vector型別的陣列即可。
intdp(
int i)}}
return dp[i];}
//呼叫printpath前需要先得到最大的dp[i],然後將i作為路徑起點傳入
void
printpath
(int i)
}
對其他的動態規劃問題而言,如果需要得到具體的最優方案,可以採用類似的方法,即記錄每次決策所選擇的策略,然後再dp陣列計算完畢後根據具體情況進行遞迴或迭代來獲取方案。
假設規定的終點為t,那麼可以令dp[i]表示從i號頂點出發到達終點t能獲得的最長路徑長度。
求解dp陣列的思想和上述一樣,區別在邊界的確定上。第乙個問題中沒有固定終點,那麼所有出度為0的頂點的dp值為0是邊界,但在這個問題中確定了終點,因此邊界為dp[t] = 0。
初始化dp陣列為乙個負的大數(-inf),來保證「無法到達終點」的含義得以表達;然後設定乙個vis陣列表示頂點是否已經被計算。
intdp(
int i)
}return dp[i]
;}
除了關鍵路徑的求解外,可以把一些問題轉換成為dag的最長路,如經典的矩形巢狀問題。
矩形巢狀問題:給出n個矩陣的長和寬,定義矩形的巢狀關係為:如果有兩個矩形a和b,其中矩形a的長和寬分別為a,b,矩形b的長和寬分別為c,d,且滿足a可以將每個矩形都看成乙個頂點,並將巢狀關係視為頂點之間的有向邊,邊權均為1,這樣就可以轉換為dag最長路問題。
動態規劃 求DAG中最長路徑
給定乙個有向無環加權圖,求圖中的最長路徑。該圖中的最長距離為14,即2 4 6 2。首先我們要對有向無環加權圖進行拓撲排序。拓撲排序的意思簡要來說就是將圖中頂點和邊排成乙個線性序列,對於,經拓撲排序後一定滿足vi在vj的前面。拓撲排序的實現方法 首先找出圖中入度為0的點加入拓撲排序後的序列,例子中為...
DAG最長路(最短路)
dag就是有向無環圖。dag上的最長或者最短路是很重要的一類問題。很多問題都可以轉化為dag上的最長或者最短路徑的問題。dag求最短和最長路的方法一樣。本演算法主要解決2個問題 1 求整個dag中的最長路徑 即不固定起點,也不固定終點 2 固定終點,求dag的最長路徑。dp i 表示從i 號頂點出發...
動態規劃 DAG模型
有n個矩形,每個矩形可以用a,b來描述,表示長和寬。矩形x a,b 可以巢狀在矩形y c,d 中當且僅當a c,b d或者b c,a d 相當於旋轉x90度 例 1,5 可以巢狀在 6,2 內,但不能巢狀在 3,4 中。你的任務是選出盡可能多的矩形排成一行,使得除最後乙個外,每乙個矩形都可以巢狀在下...