202409-小杨的武器(luogu-B4051)
GESP C++ 2024年9月五级真题,贪心思想考点,难度⭐⭐★☆☆,五级来说难度偏简单,个人认为放在四级里考也没什么问题。洛谷难度等级普及−
luogu-B4051 [GESP202409 五级] 小杨的武器
题目要求
题目描述
小杨有 种不同的武器,他对第 种武器的初始熟练度为 。
小杨会依次参加 场战斗,每场战斗小杨只能且必须选择一种武器使用,假设小杨使用了第 种武器参加了第 场战斗,战斗前该武器的熟练度为 ,则战斗后小杨对该武器的熟练度会变为 。需要注意的是, 可能是正数, 或负数,这意味着小杨参加战斗后对武器的熟练度可能会提高,也可能会不变,还有可能降低。
小杨想请你编写程序帮他计算出如何选择武器才能使得 场战斗后,自己对 种武器的熟练度的最大值尽可能大。
输入格式
第一行包含两个正整数 ,含义如题面所示。
第二行包含 个正整数 ,代表小杨对武器的初始熟练度。
第三行包含 个正整数 ,代表每场战斗后武器熟练度的变化值。
输出格式
输出一个整数,代表 场战斗后小杨对 种武器的熟练度的最大值最大是多少。
输入输出样例 #1
输入 #1
2 2
9 9
1 -1输出 #1
10说明/提示
样例 1 解释
一种最优的选择方案为,第一场战斗小杨选择第一种武器,第二场战斗小杨选择第二种武器。
数据规模与约定
| 子任务编号 | 数据点占比 | ||
|---|---|---|---|
对全部的测试数据,保证 ,。
题目分析
解题思路
问题本质
有 把武器,初始熟练度分别为 ; 场战斗,每场必须选一把武器,使用后其熟练度增加 (可正可负)。
目标:安排每把武器的使用场次,使得 场后所有武器熟练度的最大值尽可能大。关键观察
- 每场战斗只能给一把武器加 。
- 若 ,显然把它加到“当前最大值”上最划算;
若 ,把它加到“当前最小值”上,对最大值无损。
因此最优策略就是: - 若只有一把武器(),所有 无论正负都必须加在这把武器上,最终结果就是 。
- 若有多把武器(),所有正 全部累加到初始最大的那把武器上;负或零的 可以任意分配,不影响最终最大值。
算法步骤
- 读入 与初始熟练度数组 。
- 若 ,则直接累加所有 到 ,输出结果并结束。
- 否则找出初始最大值 。
- 读入 个 ,累加所有 的值到 。
- 输出 。
复杂度
- 时间:,线性扫描。
- 空间: ,存储输入。
示例代码
#include <cmath>
#include <iostream>
int n_c[100005]; // 存储 n 种武器的初始熟练度
int m_a[100005]; // 存储 m 场战斗后武器熟练度的变化值
int main() {
int n, m;
std::cin >> n >> m; // 读入武器种类数 n 和战斗场数 m
for (int i = 0; i < n; i++) {
std::cin >> n_c[i]; // 读入每种武器的初始熟练度
}
for (int i = 0; i < m; i++) {
std::cin >> m_a[i]; // 读入每场战斗的熟练度变化值
}
int ans = n_c[0]; // 初始假设最大熟练度为第一种武器
if (n == 1) {
// 只有一把武器时,所有战斗只能加在这把武器上
for (int i = 0; i < m; i++) {
ans += m_a[i];
}
} else {
// 多把武器时,先找出初始熟练度最大的武器
for (int i = 1; i < n; i++) {
ans = std::max(ans, n_c[i]);
}
// 贪心:把所有正的变化值都加给当前最大熟练度的武器
for (int i = 0; i < m; i++) {
if (m_a[i] > 0) {
ans += m_a[i];
}
}
}
std::cout << ans; // 输出最终最大熟练度
return 0;
}本文由coderli.com原创,按照CC BY-NC-SA 4.0 进行授权
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
“luogu-”系列题目可在 洛谷题库 在线评测。
“bcqm-”系列题目可在 编程启蒙题库 在线评测。
GESP/CSP认证交流QQ群: 688906745
GESP/CSP 认证学习微信公众号

最后更新于