动态规划总结


线性区间动态规划

区间最值(RMQ)静态版问题

给出序列 \(a_1 \to a_n\),有 \(l\)\(r\) ($ l - r \ge 0 $ ),使得 \(S = \sum_{i=l}^{r} a_i\) 最大,求\(S\)

状态转移方程:\(f[i]=\max\{ 0,f[i-1] \} + a_i\)。其中 \(i\) 是以 \(i\) 结尾的最大值。

样例如下:

[INPUT]
5
1 2 3 4 -114514
[OUTPUT]
10

结果就是 \(\max _{i=1} ^{i=n} f[i]\)

时间复杂度为 \(O(n)\)

参考代码如下:

int rmq(){
    memset(f,0xaf,sizeof(f));
    int result = INT_MIN;
    for(int i=1;i<=n;i++){
        f[i]=max(0,f[i-1])+a[i];
        result = max(result,f[i]);
    }
    return result;
}

最长公共子序列(LCS)

给出两个序列 \(a\)\(b\),求最长公共子序列长度。

\(i,j\)\(a[1:i],b[1:j]\)时的最长公共子序列长度。

则有:

\[\text{if } a[i] = b[j] \]

\[\text{ }f[i][j]=f[i-1][j-1]+1 \]

\[\text{else} \]

\[\text{ }f[i][j]=max \{ f[i-1][j], f[i][j-1] \} \]

时间复杂度为 \(O(n^{2})\)

int lcs(){
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(a[i]!=b[j]){
                f[i][j]=max(f[i-1][j],f[i][j-1]);
            }
            else{
                f[i][j]=f[i-1][j-1]+1;
            }
        }
    }
    return f[n][n];
}