2 条题解
-
0
这是一个功能完整的数据生成器代码(
generator.cpp)。它会根据题目要求生成 10 组测试数据(1.in/1.out到10.in/10.out),覆盖了 、 的特殊子任务,以及全正/全负变化值、极限数据范围等各种边界情况。数据生成器代码
你可以将以下代码保存为
generator.cpp,编译并运行即可。#include <iostream> #include <fstream> #include <vector> #include <string> #include <random> #include <algorithm> #include <chrono> using namespace std; typedef long long ll; // ========================================== // 1. 标准解法函数 (用于生成 .out 文件) // ========================================== ll solve(int n, int m, const vector<int>& c, const vector<int>& a) { if (n == 1) { // 情况 1: 只有一种武器,必须承担所有结果 ll ans = c[0]; for (int val : a) { ans += val; } return ans; } else { // 情况 2: 有多种武器 // 策略: 选初始值最大的作为主力,只接受正向增益 // 所有负向或0的增益交给其他武器承担 int max_c = -200000; // 题目范围 -10000,设置个足够小的初始值 for (int val : c) { if (val > max_c) max_c = val; } ll ans = max_c; for (int val : a) { if (val > 0) { ans += val; } } return ans; } } // ========================================== // 2. 随机数生成器初始化 // ========================================== mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); int rand_int(int min, int max) { uniform_int_distribution<int> dist(min, max); return dist(rng); } // ========================================== // 3. 测试点生成逻辑 // ========================================== void generate_case(int id) { int n, m; int c_min = -100, c_max = 100; int a_min = -100, a_max = 100; // 根据测试点编号配置参数,覆盖所有子任务 switch (id) { case 1: // 子任务 1: n = 1, 小数据 n = 1; m = 10; break; case 2: // 子任务 1: n = 1, 大数据,且变化值偏负 n = 1; m = 100000; a_min = -100; a_max = 50; break; case 3: // 子任务 2: m = 2, n 较小 n = 10; m = 2; break; case 4: // 子任务 2: m = 2, n 很大 n = 100000; m = 2; break; case 5: // 子任务 3: 一般情况, 变化值全为正 (贪心策略测试) n = 100; m = 100; a_min = 1; a_max = 100; break; case 6: // 子任务 3: 一般情况, 变化值全为负 (贪心策略测试: 应完全避开) n = 100; m = 100; a_min = -100; a_max = -1; break; case 7: // 子任务 3: n = 2 (最小的多武器情况), 大数据 m n = 2; m = 100000; break; case 8: // 子任务 3: n 很大, m 较小 n = 100000; m = 100; break; case 9: // 子任务 3: 满级数据, 随机 n = 100000; m = 100000; break; case 10: // 子任务 3: 满级数据, 极限数值范围 (-10000 到 10000) n = 100000; m = 100000; c_min = -10000; c_max = 10000; a_min = -10000; a_max = 10000; break; default: n = 10; m = 10; break; } // 生成数据 vector<int> c(n); vector<int> a(m); for (int i = 0; i < n; ++i) c[i] = rand_int(c_min, c_max); for (int i = 0; i < m; ++i) a[i] = rand_int(a_min, a_max); // 计算标准答案 ll ans = solve(n, m, c, a); // 写入 .in 文件 string in_file = to_string(id) + ".in"; ofstream fin(in_file); fin << n << " " << m << "\n"; for (int i = 0; i < n; ++i) fin << c[i] << (i == n - 1 ? "" : " "); fin << "\n"; for (int i = 0; i < m; ++i) fin << a[i] << (i == m - 1 ? "" : " "); fin << "\n"; fin.close(); // 写入 .out 文件 string out_file = to_string(id) + ".out"; ofstream fout(out_file); fout << ans << "\n"; fout.close(); cout << "Generated Case " << id << ": n=" << n << ", m=" << m << " -> Done." << endl; } int main() { // 生成 1 到 10 号测试点 for (int i = 1; i <= 10; ++i) { generate_case(i); } return 0; }测试点覆盖说明
- 测试点 1: ,规模小。测试当无法选择武器时的基本累加逻辑。
- 测试点 2: ,规模大 ()。测试大数据量下 的情况。
- 测试点 3: ,规模小。覆盖子任务 2 的基本情况。
- 测试点 4: ,规模大 ()。测试在大量武器中选最大值,只打两场。
- 测试点 5: ,且所有 。测试贪心逻辑是否正确累加了所有正收益。
- 测试点 6: ,且所有 。测试贪心逻辑是否正确避开了所有负收益(答案应仅为 )。
- 测试点 7: (多武器的边界),。测试只有一把“废弃”武器时能否正确承担所有负面效果。
- 测试点 8: 。测试初始查找最大值的效率。
- 测试点 9: 。综合随机大数据测试。
- 测试点 10: ,数值取到题目极限 。测试
long long是否必要以及边界数值处理。
使用方法
- 将代码保存为
generator.cpp。 - 使用 C++ 编译器编译:
g++ generator.cpp -o generator -O2。 - 运行生成的可执行文件:
./generator(Windows 下为generator.exe)。 - 运行结束后,当前目录下会出现
1.in~10.in和1.out~10.out共 20 个文件。
-
0
这是一个经典的贪心算法问题。我们需要根据武器的数量 分两种情况进行讨论。
题目分析
我们的目标是最大化最终所有武器熟练度中的最大值。
情况一:只有 1 种武器 () 如果只有一种武器,无论每场战斗后熟练度是增加还是减少,小杨都别无选择,必须使用这把武器参加所有 场战斗。 因此,最终熟练度就是:初始熟练度 + 所有战斗的变化值之和。 即:。
情况二:有多种武器 () 如果有多种武器,我们可以采取“弃车保帅”的策略。为了让某一把武器的熟练度尽可能高,我们应该:
- 选定一把初始熟练度最高的武器作为“主力”。
- 对于那些能提高熟练度()的战斗,全部安排给这把主力武器。
- 对于那些会降低或维持熟练度()的战斗,既然我们只关心最大值,我们可以把这些“坏”战斗全部安排给除主力以外的其他任意一把武器(“废弃”武器)。因为只要有至少两把武器,我们就总能找到一把不是主力的武器来承担这些负面效果,从而保护主力武器的数值不被拉低。
因此,在这种情况下,最大可能的熟练度是:所有初始熟练度中的最大值 + 所有正数变化值之和。 即:$ans = \max(c_1, \dots, c_n) + \sum_{j=1}^m \max(0, a_j)$。
C++ 代码实现
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { // 优化输入输出效率 ios_base::sync_with_stdio(false); cin.tie(NULL); int n, m; if (cin >> n >> m) { long long max_c; // 记录初始熟练度的最大值 long long c1; // 记录第一把武器的熟练度(用于 n=1 的情况) // 读取初始熟练度 for (int i = 0; i < n; ++i) { long long val; cin >> val; if (i == 0) { c1 = val; max_c = val; } else { if (val > max_c) { max_c = val; } } } long long sum_a = 0; // 所有变化值的和 long long pos_sum_a = 0; // 所有正变化值的和 // 读取战斗变化值 for (int i = 0; i < m; ++i) { long long val; cin >> val; sum_a += val; if (val > 0) { pos_sum_a += val; } } if (n == 1) { // 只有一种武器,必须承担所有战斗 cout << c1 + sum_a << endl; } else { // 多种武器,主力武器只打能加熟练度的战斗,负面战斗交给其他武器 cout << max_c + pos_sum_a << endl; } } return 0; }
- 1
信息
- ID
- 15699
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- 3
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者