4728: 【GESP2506六级】学习⼩组

内存限制:512 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:16 解决:7

题目描述

样例输入 复制

4
1 5 6 3

样例输出 复制

10

提示

题意

把 n 个人切分成若干连续小组,一个小组大小为k,贡献\(a_k\),求划分之后总贡献最大值。

dp [i]:前 i 个人划分得到的最大总积极性。

状态转移

\(dp[0]=0\)\(dp[i]=\max_{j=0}^{i-1}\big(dp[j]+a_{i-j}\big)\)

解释:前 j 个人处理完毕,把\(j+1\sim i\)划为一组,这一组人数是 \(i-j\),贡献\(a_{i-j}\)。

n≤1000,\(O(n^2)\)完全可以通过。

/*
 * 试题名称:学习小组
 * 题目大意:n名同学划分若干连续学习小组,大小k的小组贡献a[k],求总积极性最大值
 * 数据范围:n ≤ 1000,0 ≤ a_i ≤ 1e4,时间复杂度O(n^2)
 */
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 1005;
int a[N];   // a[k]:小组恰好k个人的讨论积极性
int dp[N];  // dp[i]:前i个同学划分后的最大总积极性

int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d", &a[i]);
    }

    dp[0] = 0;
    for(int i = 1; i <= n; ++i)
    {
        dp[i] = 0;
        // j是前j个人已经分完, j+1~i作为一组,组大小 i‑j
        for(int j = 0; j < i; ++j)
        {
            dp[i] = max(dp[i], dp[j] + a[i - j]);
        }
    }
    printf("%d\n", dp[n]);
    return 0;
}

#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1005;
int n;
int a[N];
int main() {
    scanf("%d", & n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", & a[i]);
        for (int j = 1; j < i; j++)
            a[i] = max(a[i], a[j] + a[i - j]);
    }
    printf("%d\n", a[n]);
    return 0;
}