1 条题解
-
0
一、 思路提示
- 浮点数的使用:
- 能量值在计算过程中会变成小数(比如乘以 0.15),所以必须使用
double类型来存储能量 。 - 输入 时也要用
double。
- 能量值在计算过程中会变成小数(比如乘以 0.15),所以必须使用
- 循环结构:
- 食物链有 层,意味着会发生 次传递。
- 我们可以写一个循环
for(int i = 1; i < N; i++)。
- 生存检查:
- 在计算每一级之前或之后,都需要检查当前能量。
- 公式逻辑:先减去消耗 ,此时要判断是否 。如果还活着,再乘以 。
- 四舍五入:
- 题目要求输出整数。C++ 中
(int)(value + 0.5)是处理正数四舍五入的常用技巧。或者使用round()函数。
- 题目要求输出整数。C++ 中
二、 预备知识点总结
- 数据类型:
double的定义与输入输出。 - 算术运算:理解百分比计算()。
- 类型转换:浮点数转整数(四舍五入)。
- 循环与中断:
break的使用(一旦灭绝立即停止)。
三、 启发式教学:草稿纸上的推理过程
教练:“我们把能量想象成水流,流过一层层的梯田。”
- 初始:
- “最大的水池(生产者)里有 10000 升水。”
- 第一层流动:
- “流向下一层前,先蒸发了 1000 升(消耗)。剩 9000。”
- “这时候水流还够吗?够(>0)。”
- “管道比较窄,只有 15% 能流下去。。”
- “第二层水池收到 1350。”
- 第二层流动:
- “蒸发 500。剩 。”
- “流下去 20%。。”
- “第三层收到 170。”
- 极端情况演示:
- “假设第三层消耗 200。。”
- “水干了!后面的老鹰(第四层)肯定没水喝了,直接饿死。输出 -1。”
四、 读题关键词总结
- “浮点数” / “四舍五入” 使用
double,最后用round或+0.5强转。 - “小于等于 0” 灭绝判断条件。
- “ 个营养级” 注意循环次数是 次(因为是传递过程,4个点只有3条边)。
五、 标准题解代码 (C++14)
/** * 题目:生态系统的能量金字塔 (Energy Pyramid) * 算法:模拟 / 浮点数运算 (Simulation / Float Math) * 难度:GESP 4级 / CSP-J T1 */ #include <iostream> #include <cmath> // 用于 round 函数 #include <iomanip> // 虽然不需要输出小数,但习惯性包含 using namespace std; int main() { // 1. 变量定义 int N; double current_energy; // 使用 double 存储能量 // 2. 输入初始数据 if (!(cin >> N >> current_energy)) return 0; // 标志位:记录是否中途灭绝 bool extinct = false; // 3. 循环模拟 N-1 次传递过程 // i 表示第 i 级向第 i+1 级传递 for (int i = 1; i < N; ++i) { int cost, rate; cin >> cost >> rate; // 步骤 A: 自身消耗 current_energy -= cost; // 检查:是否消耗完后直接归零或负数 if (current_energy <= 0) { extinct = true; break; // 能量耗尽,链条断裂 } // 步骤 B: 传递效率 (百分比) // 注意 rate 是整数,要除以 100.0 变成小数 current_energy = current_energy * (rate / 100.0); // 检查:传递后是否变得极小(虽然理论上不会变为负,但可能趋近0) // 题目要求 <= 0 即灭绝 if (current_energy <= 0) { extinct = true; break; } } // 4. 输出结果 if (extinct) { cout << -1 << endl; } else { // 四舍五入转为整数 // 方法1: (int)(current_energy + 0.5) // 方法2: round(current_energy) cout << (long long)round(current_energy) << endl; } return 0; }时间与空间复杂度分析
- 时间复杂度:
- 循环 次,每次做简单的加减乘除。
- 。
- 空间复杂度:
- 只用了几个变量。
- 。
六、 数据生成器 (Generator.cpp)
/** * 题目:生态系统的能量金字塔 * 数据生成器 */ #include <iostream> #include <fstream> #include <string> #include <vector> #include <random> #include <ctime> #include <cmath> #include <iomanip> using namespace std; mt19937 rng(time(0)); // 核心解法 long long solve(int N, double E, const vector<pair<int, int>>& params) { double cur = E; for(auto p : params) { cur -= p.first; // cost if(cur <= 0) return -1; cur = cur * (p.second / 100.0); // rate if(cur <= 0) return -1; } return (long long)round(cur); } void make_case(int id) { int N; double E; vector<pair<int, int>> params; switch(id) { case 1: // 样例 N = 4; E = 10000.0; params = {{1000, 15}, {500, 20}, {100, 10}}; break; case 2: // 第一级就死掉 N = 5; E = 100.0; params = {{200, 50}, {10, 10}, {10, 10}, {10, 10}}; break; case 3: // 效率极高 (100%) N = 5; E = 1000.0; for(int i=0; i<N-1; ++i) params.push_back({10, 100}); break; case 4: // 效率极低 (1%) N = 5; E = 1000000.0; for(int i=0; i<N-1; ++i) params.push_back({0, 1}); break; case 5: // 刚好剩下一点点 N = 3; E = 100.0; // 100 - 50 = 50; * 0.1 = 5 // 5 - 4 = 1; * 0.5 = 0.5 -> round -> 1 params = {{50, 10}, {4, 50}}; break; case 6: // 随机小数据 N = 10; E = rng()%10000 + 1000; for(int i=0; i<N-1; ++i) { int c = rng()%100; int r = rng()%20 + 5; // 5%~24% params.push_back({c, r}); } break; case 7: // 随机中数据 N = 100; E = 1000000.0; for(int i=0; i<N-1; ++i) { int c = rng()%50; int r = rng()%90 + 10; params.push_back({c, r}); } break; case 8: // 消耗很大,容易死 N = 20; E = 100000.0; for(int i=0; i<N-1; ++i) { int c = rng()%5000; int r = 20; params.push_back({c, r}); } break; case 9: // 大数据 N=1000 N = 1000; E = 1000000.0; // 为了不死,消耗必须极小,效率必须高 for(int i=0; i<N-1; ++i) { params.push_back({0, 99}); } break; case 10: // 浮点精度测试 (刚好 round 进位) N = 2; E = 10.0; // 10 - 0 = 10; * 0.15 = 1.5 -> 2 params = {{0, 15}}; break; } string in_file = to_string(id) + ".in"; ofstream fout_in(in_file); fout_in << N << " " << fixed << setprecision(1) << E << "\n"; for(auto p : params) { fout_in << p.first << " " << p.second << "\n"; } fout_in.close(); string out_file = to_string(id) + ".out"; ofstream fout_out(out_file); fout_out << solve(N, E, params) << "\n"; fout_out.close(); cout << "Generated Case " << id << endl; } int main() { for(int i=1; i<=10; ++i) make_case(i); return 0; }这道题将浮点数运算与生态系统的能量流动结合,既考察了编程基础,又强化了“能量逐级递减”的生物学概念。对于 GESP 4 级学生来说,这是练习
double类型和循环控制的绝佳题目。 - 浮点数的使用:
- 1
信息
- ID
- 19313
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 1
- 已通过
- 1
- 上传者