题目描述
一个数的序列 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
算法1
时间复杂度
$O(n^2)$
C++ 代码
#include<iostream>
using namespace std;
int main()
{
int N = 1010;
int n,w[N],cnt[N],sum[N];
cin >> n;
// cnt(i)指的是以i为结尾的子序列的个数
// 最大上升子序列 是cnt[i] = cnt[1,2,3...i-1] + 1 // 其中要去掉不是上升的子序列
// 最大上升子序列和 是sum[i] = sum[1,2,3...i-1] + w[i]
for(int i = 1;i <= n;i ++)
{
scanf("%d",&w[i]);
}
for (int i = 1; i <= n; i ++) {
cnt[i] = 1; // 每个数单独作为一个子序列
sum[i] = w[i]; // 每个数的和等于它本身
}
for(int i = 1;i <= n;i ++)
{
for(int j = 1; j < i;j ++)
{
if (w[i] > w[j])
{
cnt[i] = max(cnt[i], cnt[j] + 1);
sum[i] = max(sum[i], sum[j] + w[i]);
}
}
}
int res = 0;
for(int i = 1;i <= n;i ++)
{
res = max(res, sum[i]);
}
cout << res << endl;
return 0;
}