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;
}
本文来自博客园,作者:Cocoicobird,转载请注明原文链接:https://www.cnblogs.com/Cocoicobird/p/16826068.html
浙公网安备 33010602011771号