1. 程式人生 > 其它 >「學習筆記」動態規劃的引入

「學習筆記」動態規劃的引入

對於動態規劃進行了介紹

一.什麼是動態規劃

動態規劃是一種重要的思維方法,通過利用已有的子問題資訊高效求出當前問題的最優解。

由於動態規劃並不是某種具體的演算法,而是一種解決特定問題的方法,因此它會出現在各式各樣的資料結構中,與之相關的題目種類也更為繁雜。

二.動態規劃基礎

一般的,對於解決動態規劃的題目,有以下三個步驟:

  • 1.根據題目設計狀態,初始化狀態。
  • 2.根據狀態,推導轉移方程。(也就是考慮如何從 \(i-1\) 轉移到 \(i\)
  • 3.確定最優解,求出答案。

而動態規劃與貪心演算法本質上的區別在於:貪心演算法算出的是區域性最優解,而動態規劃算出的是全域性最優解。所以我們要認真讀題,避免判斷錯誤。

三.基本例題入門

  • P1216 [USACO1.5][IOI1994]數字三角形 Number Triangles

    讀題,按照上文分 \(3\) 步:
    • 1.設立狀態: \(dp_{i,j}\) 表示從起點到點 \(i,j\) 的最大價值,初始化 \(dp_{1,1}=a_{1,1}\)
    • 2.推導轉移方程:發現當前的 \(dp_{i,j}\) 有兩條路可以得到:從點 \(i-1,j-1\) 或點 \(i-1,j\),也就是當前點上一層的兩個點。於是轉移方程為 \(dp_{i,j}=\text{max}(dp_{i-1,j},dp_{i-1,j-1})+a_{i,j}\)
    • 3.確定最優解:題目要求求到達最底層所獲得的最大值。根據我們設計的狀態,也就是求 \(\text{max}(dp_{r,i})\)

      程式碼如下:
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e3 + 7;
    int dp[N][N], n, a[N][N];
    int main () {
    	cin >> n;
    	for (int i = 1; i <= n; i ++) {
    		for (int j = 1; j <= i; j ++) {
    			cin >> a[i][j];
    		}
    	}
    	for (int i = 1; i <= n; i ++) {
    		for (int j = 1; j <= i; j ++) {
    			dp[i][j] = max (dp[i - 1][j], dp[i - 1][j - 1]) + a[i][j];
    		}
    	}
    	int ans = 0;
    	for (int i = 1; i <= n; i ++) {
    		ans = max (ans, dp[n][i]);
    	}
    	cout << ans;
    	return 0;
    }