$$\color{Red}{最大上升子序列和}$$
我做的所有的题解
包括基础提高以及一些零散刷的各种各样的题
一个数的序列 bi,当 b1<b2<…<bS 的时候,我们称这个序列是上升的。
对于给定的一个序列(a1,a2,…,aN),我们可以得到一些上升的子序列(ai1,ai2,…,aiK),这里1≤i1<i2<…<iK≤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
证明
不要因为同一个模型求的东西变化就感觉变了,我们只是集合和存储的属性变了,但是本质还是最长上升子序列,所以我们换成结尾元素结尾的集合,属性为max即可
本题和最上上升子序列的区别就是求的是最大的序列和,那只需要让之前规划f[i]
的保存以a[i]
为结尾的最大上升子序列和,f[i] = max(f[i], f[j] + a[i])
之前有个关键点就是初始化f[i] = 1
,保证最后的结果加上了本身这个序列自己的长度,即1。这道题保存值,故要给每个f[i] = a[i]
,保证动态规划的过程中,能加上自己的这位结尾的位置的值
java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N = 1010, n;
static int[] f = new int[N];
static int[] a = new int[N];
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
n = Integer.parseInt(br.readLine());
String [] str = br.readLine().split(" ");
int res = 0;
for (int i = 1; i <= n; i++) {
a[i] = Integer.parseInt(str[i-1]);
f[i] = a[i];
for (int j = 1; j < i; j++) {
if (a[i] > a[j])
f[i] = Math.max(f[i], f[j] + a[i]);
}
res = Math.max(res, f[i]);
}
System.out.println(res);
}
}
python
N = 1010
f = [0] * N
n = int(input())
a = [0] + [int(x) for x in input().split()]
res = 0
for i in range(1, n+1):
f[i] = a[i]
for j in range(1, i):
if a[i] > a[j]:
f[i] = max(f[i], f[j] + a[i])
res = max(res, f[i])
print(res)