多階段過程轉化為一系列單階段問題,利用各階段之間的關係,逐個求解,創立了解決這類過程優化問題的新方法——動態規劃
個人的理解:就是處於當前決策時要依賴前面的已知情況,將看似」連續無統一標準解決方案「的問題分割成多個」可以商量的「的決策過程。(商量就是依靠已知的情況覺得未知)
那麼什麼問題才可以用到動態規劃呢?看問題的性質。
1. 最優子結構:
就是多步決策中的子問題的最優解也是最終問題的最優解。
2. 重疊子問題:
就是每次在求解子問題的過程中,總存在一些之前已經求出來的子問題了。
3. 無後效性:
就是當前決策只依賴於之前已經解決的結果,只對過去的歷史進行總結,並不影響未來(最近看時空穿梭看多了 - _ -|| )。
此處結合經典例題進行分析:
(石子歸併問題)
1.找出最優解的性質刻畫其結構特徵。
本質上就是找一張表來表示你要解決的問題,這個表的性質是怎麼樣的。就要依據問題最優解的結構和狀態來決定:(比如這個問題要求的最優解就是1~n堆石頭合併的最小代價。就可以求二維表中dp[1][n]的最小值,簡單的描述就是min(dp[1][n]))
2. 遞迴的定義出最優值。
換而言之就是找讓dp[1][n]盡可能小的遞推關係式,這取決於我們如何做決策,很明顯就是通過分割每個部分來進行比較哪種分割方式代價最小來決定。那麼自然而然就可以假設dp[i][j]=min(dp[i][k]+dp[k+1][j]+i~j的代價)。這樣就得到了遞推關係式,這也是dp問題的難點。
3. 以自底向上的方式求出最優解。
很顯然要到初始最小值才能得到最終最小值。只有從已知推未知,所以就要從一堆的不能分割到2堆.3堆…n堆。
ac**:
#include
#include
#include
using
namespace
std;
const
int inf = 1
<< 30;
const
int n = 205;
int dp[n][n];
int sum[n];
int a[n];
int main()
}printf("%d\n",dp[1][n]);
}return
0;}
這個石子歸併問題雖然簡單但是它充分的體現了動態規劃的所有性質,是乙個很經典的題目,可以多做一些拓展例如不是一列石頭堆,而是乙個環形的。
例題分享:
動態規劃專題
這個題,初學之時,老師教我們用分治演算法,分三路 在左邊子陣列 在右邊子陣列以及跨越中線,其實用動態規劃已經很簡單了,看狀態轉移方程就明白了 dp i beginarr i quad i 0 max quad otherwise end def maximum subarr arr if not a...
動態規劃專題
例一 有一段樓梯有10級台階,規定每一步只能跨一級或兩級,要登上第10級台階有幾種不同的走法?1 include 2 include 3 include 4 include5 using namespace std 6int solution int n 遞迴做法713 int dp 11 14in...
動態規劃專題
在 acm 能夠開展之前,必須準備預算,並獲得必要的財力支援。該活動的主要收入來自於 irreversibly bound money ibm 思路很簡單。任何時候,某位 acm 會員有少量的錢時,他將所有的硬幣投入到小豬儲錢罐中。這個過程不可逆,因為只有把小豬儲錢罐打碎才能取出硬幣。在足夠長的時間...