2022.10.25每日一题

最大和上升子序列

题目描述

给定一个长度为 \(n\) 的数组 \(a_1,a_2,…,a_n\),问其中的和最大的上升子序列。也就是说,我们要找到数组 \(p_1,p_2,…,p_m\),满足 \(1≤p_1<p_2<⋯<p_m≤n\) 并且 \(a_{p_{1}}<a_{p_{2}}<⋯<a_{p_{m}}\),使得 \(a_{p_1}+a_{p_2}+⋯+a_{p_m}\) 最大。

输入格式

第一行一个数字 \(n\)
接下来一行 \(n\) 个整数 \(a_1,a_2,…,a_n\)

输出格式

一个数,表示答案。

样例输入
6
3 7 4 2 6 8
样例输出
21
数据范围

所有数据保证 \(1≤n≤1000,1≤a_i≤10^5\)

解题思路
  • 状态表示 \(p[i]\):表示的是前 \(i\) 个元素中的上升子序列和的最大值
  • 状态计算/集合划分:将 \(p[i]\) 划分为 \(i-1\) 个集合,表示上升子序列前一个元素是 \(a[j],j\in [1,i-1]\),因此如果 \(a[i]\gt a[j]\),则子序列和为 \(p[j]+a[i]\),否则子序列和就是 \(p[j]\),故状态方程为 \(p[i] = max(p[i], p[j] + a[i])\)
C++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010, mod = 1e9 + 7;

int n;
int a[N], p[N]; //p[i] 表示前 i 个元素中上升子序列的最大和

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
        scanf("%d", &a[i]);
    for(int i = 1; i <= n; i ++)
        p[i] = a[i];
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j < i; j ++)
        {
            if(a[i] > a[j])
                p[i] = max(p[i], p[j] + a[i]);
        }
    int res = 0;
    for(int i = 1; i <= n; i ++)
        res = max(res, p[i]);
    printf("%d\n", res);
    return 0;
}
posted @ 2022-10-25 19:42  Cocoicobird  阅读(34)  评论(0)    收藏  举报