有關動態規劃問題DP的詳細講解

2021-09-27 02:44:33 字數 1897 閱讀 9329

首先我們要注意,我們學習dp主要是學一種解決問題的思想,而不是一種演算法。

動態規劃的思想

動態規劃是求解多階段決策過程最優化的方法。

通過把多階段過程轉化為一系列的單階段問題,利用各階段之間的關係,逐個求解。

找到各階段之間的關係是難點。

舉個栗子~

矩陣取數問題

從矩陣的左上走到右下,每次只能向右或者向下走,問怎樣走才能使得最後走過路徑的和最 大。

分析

當然可以用bfs, dfs去暴力搜尋出所有的矩陣,但是暴力完全體現不出任何優美。 如果用的思想,應該怎麼做?? 首先我們想到的一定是貪心策略,每次只能向右或者向下兩種選擇,那麼 是不是只要每次都選擇 右面和下面 的中,其元素最大的那個方向,最後的答案就是最大的呢?

用貪心的方法,答案是9. 但是顯然有乙個更大的答案 10 ,這個答案是如何得出的?

如果你崇尚暴力的美學,當然也可以把所有的路徑搜出來求乙個最大值,但是請自行算當n=500時 有多少條路。

我們來用dp的思想來解決這個問題x 設矩陣是 . 假設我們已經知道了最大路徑,並且經過(x, y)這個位置,為了從起點到終點得到的和最大,那 麼從起點到 (x , y) 經過的數的和也一定要最大。這幾乎是顯然的。

這是理解這一題的重點。

走到 (x, y) 的上一步,可能是 (x-1, y) 或者(x, y-1). 按照我門上面得出的結論,我們可以這樣說: 如果從起點達到(x,y)的最優路徑要經過(x – 1,y)或者(x,y – 1)則,從起點到達(x – 1,y)或者(x,y – 1)的 路徑一定也必須是最優的。

所以只需要比較 到達(x – 1,y)或者(x,y – 1)的最優路徑哪乙個更加優。為了方便表示,我們用:f(x,y) 來表示起點到 (x,y)的最優路徑長度。 所以,起點到 (x,y)的最優路徑可以表示成:

f(x,y) = max(f(x-1),y),f(x,y-1))+a[x][y];
到了這裡肯定會有疑問了,這怎麼感覺和上面的貪心策略差不多??

其實不,這裡是理解dp的重點。根據上面的這個遞推公式,我門可以準確的推導出從起點到所有點 的最優解。是整體的最優。而貪心策略只是在區域性做選擇,是區域性的最優。

**實現如下

#includeusing namespace std;

const int maxn=500+10;

int a[maxn][maxn];

int main()

}

這已經是可以用動態規劃思想去考慮的最簡單的問題了, 每一步的決策無非就是,是否繼續把下乙個元素加入當前的子段.

動態規劃大顯身手。我們開乙個陣列dp , 記錄dp[i]表示以a[i]結尾的 全部子段中 最大的那個的 和。 這樣我們就可以根據它dp[i] 的正負,去考慮是否把下乙個元素加入到當前的子段。 如果dp[i] 是負數,那麼我們為什不從a[i+1]新維護乙個子段呢? 如果dp[i] 是正數,那麼顯然可以繼續把a[i+1] 加入到當前的子段。

最後我們只需要找出所有最大子段中,最大的那個。

#include #include using namespace std; 

const int maxn = 50000+10;

long long a[maxn];

int main()

cout << ans << endl;

return 0;

}

dp(動態規劃問題)

先講一下dp的一般思路吧 將原問題分解為子問題 1 把原問題分解為若干個子問題,子問題和原問題形式相同 或類似,只不過規模變小了。子問題都解決,原問題即解 決 數字三角形例 2 子問題的解一旦求出就會被儲存,所以每個子問題只需求解一次。確定狀態 在用動態規劃解題時,我們往往將和子問題相關的各個變數的...

DP問題集 動態規劃試題

1.揹包問題 給定n種物品和一揹包。物品i的重量是wi,其價值為pi,揹包的容量為c。問應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?分析 每個物品只有兩種選擇,要麼就是塞到包裡面,要麼就是不要了 當揹包剩餘容量為j時,如果第i件物品重量wi j時,必定是要不了的,如果wi 假設剩餘容量...

DP 動態規劃 揹包問題

將乙個容量為v的揹包,物品有兩個屬性,乙個w和乙個v表示體積和屬性值。每種物品只有乙個。要求裝下盡可能多,求最大價值。轉移狀態方程 dp j max dp dp j list i w list i v,dp j 1 include includeusing namespace std struct ...