DP

動態規劃

簡單來說,動態規劃就是用空間換取時間。先把算過的答案存起來,再用原有的東西計算出新的,避免重複計算答案。

分析複雜度

  • 狀態數
  • 轉移式
  • 把上面乘起來就是了

01 背包問題

有個背包能裝 W 重量的東西,有 n 樣物品,每種物品都有其價值 v 和重量 w,問能裝物品的最大價值?

最長公共子序列(LCS)

給定兩組序列:

s1 : a1, a2, a3, a4......

s2 : b1, b2, b3......

一個子序列 ai, aj, ak...... 滿足 i < j

舉例來說,7122, 712, 71, 7 的子序列可以是

7122, 71, 7、712, 71等等

現在問兩序列的最長公共子序列?

TIOJ

  • 1007
  • 1060
  • 1354
  • 1883

Longest Increasing Subsequence ( LIS )

  • subsequence 指的是「子序列」
    就是在一個數列中按照左右的相對位置,挑幾個數字出來
  • increasing 指「嚴格遞增」
  • 比如說「1, 3, 5, 2, 7, 8, 3, 9」中,
    LIS 為 「1, 3, 5, 7, 8, 9」
  • 一個一個找出後面能接上哪些數字
  • 別擔心有複雜度更好的
O(n^{2})
O(n2)O(n^{2})
int s[n], l[n]; // s = sequence, l = length
int LIS(){
    for(int i = 0; i < n; i++) l[i] = 1;
    for(int i = 0; i < n; i++){
        for(int j = i+1; j < n; j++)
            if(s[i] < s[j])
                l[j] = max(l[j], l[i]+1);
    }
    int max = 0;
    for(int i = 0; i < n; i++)
        if(max < l[i]) l[i] = max;
    return max;
}
O(n logn)
O(nlogn)O(n logn)
vector<int> s;
int LIS(vector<int> s){
    if(s.size() == 0) return 0;
    vector<int> v;
    v.push_back(s[0]);
    for(int i = 1; i < s.size(); i++){
        if(s[i] > v.back()) v.push_back(s[i]);
        else *lower_bound(v.begin(), v.end(), s[i]) = s[i];
    }
    return v.size();
}

滾動 DP

  • 一種減少空間複雜度的技巧

UVa

  • 103
  • 111
  • 231
  • 437

TIOJ

  • 1103

Dynamic Programming

By hfy880916

Dynamic Programming

  • 607