The second dynamic programming: linear dp interval dp

One, linear dp

(1) Digital triangle

Find the maximum path from top to bottom, each time there are two cases, the maximum value is passed down from the upper left, and the maximum value is passed down from the upper right.

f[i][j] = max(f[i - 1][j - 1] + a[i][j], f[i - 1][j] + a[i][j]);

(2) The longest ascending subsequence

for(int i = 1; i <= n; i ++)
{
    
    
    f[i] = 1;
    for(int j = 1; j < i; j ++)
    {
    
    
        if(a[j] < a[i])
            f[i] = max(f[i], f[j] + 1);
    }
}

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10;

//最长上升子序列进阶
int n;
int a[N];
int q[N];
int main()
{
    
    
    cin >> n;
    for(int i = 0; i < n; i ++) cin >> a[i];
    int len = 0;
    q[0] = -2e9;
    for(int i = 0; i < n; i ++)
    {
    
    
        int l = 0, r = len;
        while(l < r)
        {
    
    
            int mid = l + r + 1 >> 1;
            if(q[mid] < a[i]) l = mid;
            else r = mid - 1;
        }
        len = max(len, r + 1);
        q[r + 1] = a[i];
    }
    cout << len << endl;
}

(3) The longest common subsequence

f[i][j] = max(f[i - 1][j], f[i][j - 1]);
if(a[i] == b[j]) f[i][j] = max(f[i - 1][j - 1] + 1, f[i][j]);

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N = 2e3 + 10;

//给出两个字符串,把a转换成b需要至少多少操作,有三个操作可以选择,删除一个字母,增加一个字母,改变一个字母。
int n, m;
char a[N], b[N];
int f[N][N];
int main()
{
    
    
    cin >> n >> a + 1;
    cin >> m >> b + 1;
    for(int i = 0; i <= m; i ++) f[0][i] = i;//当用a的前0个字母和b的前i个字母匹配时,需要在a加上i个字母。
    for(int i = 0; i <= n; i ++)
        f[i][0] =
            i;  //当用a的前i个字母和b的前0个字母匹配时,需要在a减去i个字母。
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
        {
    
    
            f[i][j] = min(f[i - 1][j] + 1, f[i][j - 1] + 1);
            if(a[i] == b[j]) f[i][j] = min(f[i][j], f[i - 1][j - 1]);//如果相等,不用操作。
            else f[i][j] = min(f[i][j], f[i - 1][j - 1] + 1);//如果不相等需要修改。
        }
    cout << f[n][m] << endl;
}


Two, interval dp

Merge stones

int  main()
{
    
    
    int n;
    int s[510];
    int f[510][510];
    for(int i = 1; i <= n; i ++) cin >> s[i];
    for(int i = 0; i <= n; i ++) s[i] += s[i - 1]; //求前缀和
    for(int len = 2; len <= n; len ++)//枚举长度
        for(int i = 1; i + len - 1 <= n; i ++)
        {
    
    
            int l = i, r = i + len - 1;
            f[l][r] = 1e8;
            for(int k = l; k < r; k ++)
                f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r] + s[r] - s[l - 1]);
        }
    cout << f[1][n];
}

Guess you like

Origin blog.csdn.net/qq_47783181/article/details/112765435