题解:洛谷 B4051 小杨的武器
【题目来源】
洛谷:B4051 [GESP202409 五级] 小杨的武器 - 洛谷
【题目描述】
小杨有\(n\)种不同的武器,他对第 \(i\) 种武器的初始熟练度为\(c_i\)。
小杨会依次参加\(m\) 场战斗,每场战斗小杨只能且必须选择一种武器使用。假设小杨使用了第\(i\)种武器参加了第\(j\)场战斗,战斗前该武器的熟练度为\(c'_i\),则战斗后小杨对该武器的熟练度会变为\(c'_i+a_j\)。需要注意的是\(a_j\)可能是正数、0或负数,这意味着小杨参加战斗后对武器的熟练度可能会提高,也可能会不变,还有可能降低。
小杨想请你编写程序帮助他计算出如何选择武器才能使得\(m\) 场战斗后,自已对\(n\)种武器的熟练度的最大值尽可能大。
【输入】
第一行包含两个正整数\(n\),\(m\),含义如题面所示。
第二行包含\(n\)个正整数\(c_1,c_2,\dots,c_n\),代表小杨对武器的初始熟练度。
第三行包含\(m\)个正整数\(a_,a_2,\dots, a_m\),代表每场战斗后武器熟练度的变化值。
【输出】
输出一个整数,代表\(m\) 场场战斗后小杨对\(n\)种武器的熟练度的最大值最大是多少。
【输入样例】
2 2
9 9
1 -1
【输出样例】
10
【核心思想】
-
问题分析:给定 \(n\) 种武器的初始熟练度 \(c_i\) 和 \(m\) 场战斗的熟练度变化值 \(a_j\)。每场战斗必须选择一种武器,该武器熟练度增加 \(a_j\)。求 \(m\) 场战斗后所有武器熟练度最大值的最大可能值。这是一个贪心策略问题,核心在于分析如何将每场战斗的增益分配给最优武器。
-
算法选择:
- 贪心分配:将最大初始熟练度的武器作为"主武器",所有正增益都分配给该武器;负增益分配给非主武器(或当只有 \(1\) 种武器时不得不承受)
- 最大值维护:只需追踪当前最大熟练度,无需维护所有武器状态
-
关键步骤:
- 读入数据:读取 \(n, m\),初始熟练度 \(c[1..n]\),战斗增益 \(a[1..m]\)
- 确定主武器:\(mx \leftarrow \max_{i=1}^{n} c_i\),即初始最大熟练度
- 处理每场战斗(\(j\) 从 \(1\) 到 \(m\)):
- 若 \(n = 1\)(只有一把武器):\(mx \leftarrow mx + a_j\)(所有变化都作用于该武器)
- 否则若 \(a_j > 0\):\(mx \leftarrow mx + a_j\)(正增益分配给当前最强武器,使其更强)
- 否则:不操作(负增益分配给非主武器,不影响最大值)
- 输出结果:\(mx\)
-
时间/空间复杂度:
- 时间复杂度:\(O(n + m)\),遍历初始熟练度和战斗增益各一次
- 空间复杂度:\(O(n + m)\),存储输入数组
-
贪心策略的核心思想:
- 集中优势资源:所有正增益都集中分配给当前熟练度最高的武器,使其始终保持最大,这是最大化最终最大值的贪心策略
- 负增益的规避:当有多种武器时,负增益可以分配给非主武器,不影响最大熟练度。只有一把武器时无法规避,必须承受
- 最优子结构:每场战斗的最优决策只依赖于当前最大熟练度,与具体是哪把武器无关,因此只需维护最大值
- 单调性保证:正增益使最大值增加,负增益不减少最大值(当 \(n \geq 2\) 时),因此最终最大值具有单调不减性
- 适用于资源集中分配、最大化极值类贪心问题
【算法标签】
普及- #贪心
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 100010; // 定义数组大小常量
int a[N], c[N]; // 定义两个数组,一个存储每场战斗的增益值,一个存储初始熟练度
int main()
{
int n, m; // 定义变量n和m,分别表示武器种类数和战斗次数
cin >> n >> m; // 输入n和m
int mx = -10000; // 初始化最大熟练度为一个较小的值
for (int i=1; i<=n; i++) { // 循环输入每种武器的初始熟练度
cin >> c[i];
mx = max(mx, c[i]); // 更新当前最大熟练度
}
for (int i=1; i<=m; i++) { // 循环输入每场战斗的增益值
cin >> a[i];
}
for (int i=1; i<=m; i++) { // 根据战斗增益更新最大熟练度
if (n==1 || a[i]>0) { // 如果只有一种武器或者当前战斗增益为正
mx += a[i]; // 增加最大熟练度
}
}
cout << mx << endl; // 输出最终的最大熟练度
return 0;
}
【运行结果】
2 2
9 9
1 -1
10
浙公网安备 33010602011771号