✏️ 纠错
第 134 题 / 共 155 题

题目描述

班主任计划将班级里的 n 名同学划分为若干个学习小组,每名同学都需要分入某一个学习小组中。观察发现,如果一个学习小组中恰好包含 k 名同学,则该学习小组的讨论积极度为 ak​。

给定讨论积极度 a1​,a2​,…,an​,请你计算将这 n 名同学划分为学习小组的所有可能方案中,讨论积极度之和的最大值。

输入格式

第一行,一个正整数 n,表示班级人数。

第二行,n 个非负整数 a1​,a2​,…,an​,表示不同人数学习小组的讨论积极度。

输出格式

输出共一行,一个整数,表示所有划分方案中,学习小组讨论积极度之和的最大值。

输入输出样例

输入 #1

4
1 5 6 3

输出 #1

10

输入 #2

8
0 2 5 6 4 3 3 4

输出 #2

12

说明/提示

对于 40% 的测试点,保证 1≤n≤10。

对于所有测试点,保证 1≤n≤1000,0≤ai​≤104。

📝 题目解析

【题目大意】将n名学生进行分组,要求每位学生都必须被分配到某个小组中,规定一个由k人组成的小组其积极度为ak,需计算出积极度总和的最大值。

【考纲知识点】动态规划知识

【解题思路】在本题中,参数n兼具两个含义,既表示物品的数量,又代表背包的容量。第k个物品的体积为k,价值为ak。由于每种物品可被选用的次数不受限制,能够被使用无数次,因此该问题属于完全背包问题。 本题的要点是熟悉完全背包类型的动态规划求解。

参考程序

#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 1005;

int n;
int a[N], f[N];

int main() {
    int ans = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        for (int j = i; j <= n; j++)
            f[j] = max(f[j], f[j - i] + a[i]);
    }

    for (int i = 1; i <= n; i++)
        ans = max(ans, f[n]);

    printf("%d\n", ans);
    return 0;
}