信奥赛CSP-J复赛集训(模拟算法专题)(9):P6437 [COCI 2011/2012 #6] JACK
信奥赛CSP-J复赛集训(模拟算法专题)(9):P6437 [COCI 2011/2012 #6] JACK
题目描述
给定 n n n 个正整数 a 1 … a n a_1 \dots a_n a1…an,请从中选择 3 3 3 个数字,满足他们的和不大于给定的整数 m m m,请求出这个和最大可能是多少。
输入格式
第一行有两个整数,分别表示数字个数 n n n 和给定的整数 m m m。
第二行有 n n n 个整数,表示给定的 n n n 个数字 a i a_i ai。
输出格式
输出一行一个整数表示答案。
输入输出样例 #1
输入 #1
5 21
5 6 7 8 9
输出 #1
21
输入输出样例 #2
输入 #2
10 500
93 181 245 214 315 36 185 138 216 295
输出 #2
497
说明/提示
数据规模与约定
- 对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 100 1 \leq n \leq 100 1≤n≤100, 6 ≤ m ≤ 3 × 1 0 5 6 \leq m \leq 3 \times 10^5 6≤m≤3×105, 1 ≤ a i ≤ 1 0 5 1 \leq a_i \leq 10^5 1≤ai≤105,数据保证有解。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int n, m, a[110], sum, ans = -1; // ans初始化为-1,表示无解的情况
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> a[i]; // 输入n个数字到数组a中
// 三重循环枚举所有可能的三元组(i, j, k)
for(int i = 1; i <= n; i++) { // 枚举第一个数的索引i
for(int j = 1; j <= n; j++) { // 枚举第二个数的索引j
for(int k = 1; k <= n; k++) { // 枚举第三个数的索引k
// 确保三个索引互不相同(不同位置的元素)
if(j != i && k != i && k != j) {
sum = a[i] + a[j] + a[k]; // 计算三数之和
// 若和不超过m,则更新最大值
if(sum <= m)
ans = max(ans, sum);
}
}
}
}
cout << ans; // 输出结果(若未更新则保持-1)
return 0;
}
功能分析
-
问题目标
从数组中选取三个不同位置的元素,使其总和不超过给定值m
,同时尽可能接近m
。若不存在合法组合,输出-1
。 -
核心逻辑
- 三重循环暴力枚举:通过遍历所有可能的索引组合
(i, j, k)
,确保三个索引互不相同(j != i
、k != i
、k != j
),以此选取三个不同位置的元素。 - 合法性检查:计算三数之和
sum
,若其不超过m
,则用max
函数维护最大值ans
。
- 三重循环暴力枚举:通过遍历所有可能的索引组合
-
时间复杂度
三重循环的时间复杂度为O(n³),适用于n
较小的情况(如题目隐含的n ≤ 100
)。
文末彩蛋:
点击查看老师的个人主页,学习csp信奥赛完整系列课程:
https://edu.csdn.net/lecturer/7901