因为思路上是线性的,一行一行(列)的做,所以说是线性的
数字三角形
从最上层走到最下层,找到路径上的数加起来最大的路线
状态表示
走到(i, j)点的过程中,所有可能路径的最大值
状态计算
要分类看: 走到一个点,要么是从左上角来的,要么是从右上角来的,由此分为两类,按行和斜对角来计数
9(3,2) 2(2,1) 4(2,2) 走到9,必是从2,或4来的,走到9了要最大,即走到2或走到4时也是最大(因为9一定经过,要最大路径就得本来是最大路径) 即线性规划 2024-03-10 21.39.24.excalidraw
⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠
Excalidraw Data
Text Elements
1
2, 3
7 4 8
10 9 6 5
Link to original
f[i][j] = max(f[i-1][j-1] + a[i][j], f[i-1][j] + a[i][j])
因为边缘的点可能没有左上或右上,所以要无效化这些路径
实现
//利用负无穷和max来将没有的路径无效化
for(int i = 0; i <= n; i ++)
for(int j = 0; j <= i + 1; j ++)
f[i][j] = -INF;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= i; j ++)
cin >> a[i][j];
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] + a[i][j], f[i-1][j] + a[i][j]);
//遍历找底层最大值
int ans = -INF;
for(int i = 1; i <= n; i ++)
ans = max(ans, f[n][i]);
上升子序列
上升子序列,方向是确定,从左到右的,是严格单调的递增序列,可以是离散的不同子序列
状态表示
到第i个数的上升序列中,最长的子序列的长度
状态计算
分类:
到第i个数的上升子序列的前一个数(倒数第二个数)分类,分为n类,每一类的最长上升子序列是 f[i] = max(f[1] + 1, f[2] + 1, f[3] + 1 …… f[i-1] + 1
条件是分类的数和第i个数构成上升关系
实现
for(int i = 1; i <= n; i ++)
{
f[i] = 1; //f[i]最小也是1
for(int j = 1; j <= n; j ++)
if(a[i] > a[j])
f[i] = max(f[j] + 1, f[i]);
}
int g[N]; //记录第i个数的最长子序列是从哪个数继承过来的
for(int i = 1; i <= n; i ++)
{
f[i] = 1;
for(int i = 1; i <= n; i ++)
{
if(a[i] > a[j])
{
if(f[i] < f[j] + 1)
{
f[i] = f[j] + 1;
g[i] = j;
}
}
}
//逆序输出g
int ans = 0;
for(int i = 1; i <= n; i ++)
{
if(f[i] > f[ans])
ans = i;
}
for(int i = 0; i < f[ans]; i ++)
{
cout << a[ans];
ans = g[ans];
}
}
最长公共子序列
两个字符串中,最长的公共子序列
状态表示
遍历到第一串的 i 和第二串的 j 时,最长的公共子序列的长度
状态计算
分类:
- i 和 j 都不选的子序列
- i 选 j 不选的子序列
- j 选 i 不选的子序列
- i 和 j 都选的子序列
可以得到 f[i-1][j-1] f[i][j - 1] f[i - 1][j] f[i - 1][j - 1] + 1
其中,f[i][j - 1] f[i - 1][j]
并不表示 i 一定选(j 一定选)的最长子序列,会包含都不选的情况,但没有都选的情况,二者的集合是有重叠的,但是不影响求最大值
实现
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
{
//f[i][j]中,要么选了i进来,要么选了j进来,要么都不选
//都不选包含在选了一个的最大值里面
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
//要相等才可以都选
if(a[i] == b[j]) f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1);
}