top1编程
← 返回题目
题解

寻找最大和

1 条题解

  • 0
    @ 2026-8-5 22:45:01

    P4706 寻找最大和(入门)

    解题思路

    有 n 个数,要从中挑出 3 个数,让它们的和不超过 m,并且让这个和尽量大。如果怎么挑都会超过 m,就输出 0。

    n 的规模不大,所以可以暴力枚举:用三重循环把所有的"选 3 个数"的组合都试一遍。第一层循环定第一个数 i,第二层定第二个数 j(从 i 后面开始),第三层定第三个数 k(从 j 后面开始),这样每个组合恰好被算一次,不会重复也不会漏。让 j 从 i+1 开始、k 从 j+1 开始,是为了保证 i、j、k 互不相同,并且同一个组合不会被重复计算。比如选了 (5,6,7),就不会再选 (6,5,7),因为第二层永远取的是后面的数。

    每试一个组合,算出 s = a[i]+a[j]+a[k]。如果 s ≤ m,说明这个组合合格;再和之前找到的最好答案比较,如果更大就更新。循环结束后,ans 里存的就是不超过 m 的最大和。如果一次都没更新,ans 保持初始值 0,正好符合"没有则输出 0"的要求。

    举个例子:5 个数 5 6 7 8 9,m=21。试组合:5+6+7=18,5+6+8=19,5+7+9=21……最大合格的和是 21(5+7+9 或 6+7+8),输出 21。

    边界情况:如果 n 小于 3,根本选不出 3 个数,应该输出 0;三个数相加可能超过 int 的范围,所以用 long long 存和。

    参考代码

    // 寻找最大和:从 n 个数中选 3 个,和不超过 m 时求最大和
    #include <iostream>
    using namespace std;
    
    int a[1005];
    
    int main() {
        int n;
        long long m;
        cin >> n >> m;
        for (int i = 0; i < n; i++) cin >> a[i];
        long long ans = 0; // 找不到符合条件的三数就输出 0
        // 三重循环枚举三个数
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                for (int k = j + 1; k < n; k++) {
                    long long s = a[i] + a[j] + a[k];
                    if (s <= m && s > ans) ans = s; // 更新最优答案
                }
            }
        }
        cout << ans << endl;
        return 0;
    }
    

    复杂度分析

    三重循环,每层最多 n 次,时间复杂度 O(n³)。在 n 不大的时候(几百以内)完全没问题。空间 O(n) 用来存这 n 个数。

    • 1