线性DP
数字三角形
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
#include<iostream>
#include<algorithm>
using namespace std;
int n;
const int N = 510, INF = 1e9;
int a[N][N];
int f[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=0;i<=n;i++)
for(int j=0;j<=i+1;j++)
f[i][j] = -INF;
f[1][1] = a[1][1];
for(int i=2;i<=n;i++)
for(int j=1;j<=i;j++)
f[i][j] = max(f[i-1][j-1],f[i-1][j]) + a[i][j];
int res = -INF;
for(int i=1;i<=n;i++)
res = max(res, f[n][i]);
cout << res << endl;
return 0;
}
最长上升子序列
给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。
基础写法
#include <iostream>
using namespace std;
const int N = 1010;
int n;
int w[N], f[N];
int main(){
cin >> n;
for(int i=0;i<n;i++) cin >> w[i];
for(int i=0;i<n;i++){
f[i] = 1;
for(int j=0;j<i;j++){
if(w[j] < w[i]){
f[i] = max(f[j] + 1, f[i]);
}
}
}
int res = 0;
for(int i=0;i<n;i++){
res = max(res, f[i]);
}
cout << res << endl;
return 0;
}
最长公共子序列
给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。
#include <iostream>
using namespace std;
const int N = 1010;
int n, m;
char a[N], b[N];
int f[N][N];
int main(){
cin >> n >> m >> a + 1 >> b + 1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i]==b[j]){
f[i][j] = f[i - 1][j - 1] + 1;
}
else{
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
}
}
}
cout << f[n][m] << endl;
return 0;
}