Skip to content

03532: 最大上升子序列和

dp, http://cs101.openjudge.cn/practice/03532

一个数的序列bi,当b~1~ < b~2~ < ... < b~S~的时候,我们称这个序列是上升的。对于给定的一个序列(a~1~, a~2~, ...,a~N~),我们可以得到一些上升的子序列(a~i1~, a~i2~, ..., a~iK~),这里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 (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000(可能重复)。

输出

最大上升子序列和

样例输入

7
1 7 3 5 9 4 8

样例输出

18

思路:从第一个数开始逐次递推,考虑第 i个数的情况时,再从第一个数开始逐个检验,如果第 i个数大于前 i个数中的第 j个数,那么将前 j个数的最大上升子序列和再加上第 i个数,即构成前 i个数上升子序列和的一种情况,再取这些情况中的最大值,即得到前 i个数的最大上升子序列和。最后依次递推,即可得到整个序列的最大上升子序列和。

主要思路就是记录把每个数作为序列最后一位时的序列和,取 max。即,以每一项为末项的最大上升子序列和。

2020fall-cs101,邹思清。感觉跟我之前做的dp不太一样。之前的dp大多是计算n位之前满足的答案,而这道题使用的递推公式也不仅仅是相邻几项,而且还使用了max,做的时候没有想到,又学到新方法了。

python
input()
b = [int(x) for x in input().split()]

n = len(b)
dp = [0]*n

for i in range(n):
    dp[i] = b[i]
    for j in range(i):
        if b[j]<b[i]:
            dp[i] = max(dp[j]+b[i], dp[i])
    
print(max(dp))

2020fall-cs101,李东航

python
import copy
n = int(input())
a = list(map(int, input().split()))
dp = copy.deepcopy(a)
for i in range(n):    
    for j in range(i):        
        if a[j] < a[i]:            
            dp[i] = max(dp[j] + a[i], dp[i])

print(max(dp))

2020fall-cs101,章斯岚。这里用i+1是为了防止a[0:i]可能是空列表导致runtime error

python
dp = [0]*(10000+2)
input()
for i in map(int, input().split()):
    dp[i+1] = max(dp[0:i+1]) + i
print(max(dp))