宣传一下算法提高课整理 <—
本题链接(AcWing)
https://www.acwing.com/problem/content/1018/
题目描述
一个数的序列 $b_i$,当 $b_1<b_2<…<b_S$ 的时候,我们称这个序列是上升的。
对于给定的一个序列$(a_1,a_2,…,a_N)$,我们可以得到一些上升的子序列$(a_{i_1},a_{i_2},…,a_{i_K})$,这里$1≤i_1<i_2<…<i_K≤N$。
比如,对于序列(1,7,3,5,9,4,8),有它的一些上升子序列,如(1,7),(3,4,8)等等。
这些子序列中和最大为18,为子序列(1,3,5,9)的和。
你的任务,就是对于给定的序列,求出最大上升子序列和。
注意,最长的上升子序列的和不一定是最大的,比如序列(100,1,2,3)的最大上升子序列和为100,而最长上升子序列为(1,2,3)。
输入格式
输入的第一行是序列的长度N。
第二行给出序列中的N个整数,这些整数的取值范围都在0到10000(可能重复)。
输出格式
输出一个整数,表示最大上升子序列和。
数据范围
$1≤N≤1000$
样例输入
7
1 7 3 5 9 4 8
样例输出
18
思路
本题为DP问题,可以使用闫氏DP分析法解题。
DP:
- 状态表示$f[i]$:
······集合:以$a[i]$结尾的每个上升子序列的和
······属性:$\max$ - 状态计算:
······与LIS问题如出一辙,具体看代码
$AC$ $Code$:
$C++$
#include <iostream>
using namespace std;
const int N = 1010;
int n;
int a[N];
int f[N];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
scanf("%d", &a[i]); // 读入
for (int i = 1; i <= n; i ++ )
{
f[i] = a[i]; // 序列中只有a[i]一个数的情况
for (int j = 1; j < i; j ++ )
if (a[j] < a[i]) // 如果序列满足上升
f[i] = max(f[i], f[j] + a[i]); // 取所有以a[i]结尾的序列之和的最大值
}
int res = 0;
for (int i = 1; i <= n; i ++ )
res = max(res, f[i]); // 刷一遍f数组找最大值
printf("%d\n", res);
return 0;
}
最后,如果觉得对您有帮助的话,点个赞再走吧!