1. 项目概述:东华OJ基础题44-三艘船(C++)
这道题目来自东华大学在线判题系统(OJ)的基础题库,编号44,题名为"三艘船"。作为C++编程的入门练习题,它主要考察学生对基础语法、逻辑控制和简单算法的掌握程度。这类题目在高校程序设计课程中非常典型,通常作为课后作业或期中考试的题型出现。
从题目名称"三艘船"可以推测,这可能是一个与船只调度、运输或排列组合相关的计算问题。在东华OJ系统中,基础题系列的特点是:
- 问题描述清晰明确
- 输入输出格式规范
- 不需要复杂的数据结构
- 主要测试基础编程能力
这类题目特别适合刚学完C++基础语法的学生练习,帮助他们将理论知识转化为实际编码能力。通过解决这类问题,学生可以巩固以下核心技能:
- 变量定义与使用
- 条件判断(if-else/switch)
- 循环结构(for/while)
- 基本输入输出(cin/cout)
- 简单算法设计
提示:在开始编码前,务必仔细阅读题目描述,明确输入输出要求,这是解决OJ题目的第一步也是最重要的一步。
2. 题目分析与解题思路
2.1 题目内容推测
虽然无法看到原题描述,但根据"三艘船"这个标题和东华OJ基础题的特点,我们可以合理推测题目可能涉及以下一种或几种情况:
- 船只调度问题:可能给定三艘船的一些属性(如容量、速度等),要求计算最优调度方案
- 运输计算问题:可能涉及货物在三艘船之间的分配或运输次数计算
- 排列组合问题:可能要求计算三艘船的不同排列方式或组合情况
- 时间计算问题:可能涉及三艘船到达或离开港口的时间计算
2.2 常见解题方法
对于这类基础题目,通常可以采用以下方法解决:
- 输入解析:首先读取并解析输入数据,可能需要处理多组测试用例
- 变量定义:根据题目要求定义合适的变量存储数据
- 条件判断:使用if-else或switch语句处理不同情况
- 循环控制:可能需要for或while循环来处理重复计算
- 结果输出:按照题目要求的格式输出计算结果
2.3 具体实现思路
假设题目是关于三艘船的运输能力计算(这是最常见的情况),我们可以这样设计解决方案:
- 定义变量存储三艘船的容量
- 读取输入的总货物量
- 计算需要多少趟运输(考虑不同船的容量组合)
- 输出最终运输次数
#include <iostream> using namespace std; int main() { int ship1, ship2, ship3; // 三艘船的容量 int totalCargo; // 总货物量 cin >> ship1 >> ship2 >> ship3 >> totalCargo; // 计算最少运输次数 int trips = 0; while(totalCargo > 0) { if(totalCargo >= ship1) { totalCargo -= ship1; } else if(totalCargo >= ship2) { totalCargo -= ship2; } else { totalCargo -= ship3; } trips++; } cout << trips << endl; return 0; }3. 代码实现与优化
3.1 基础实现版本
基于上述思路,我们可以先实现一个基础版本。假设题目要求计算用三艘不同容量的船运输所有货物所需的最少趟数:
#include <iostream> #include <algorithm> // 用于sort函数 using namespace std; int main() { int ships[3]; // 存储三艘船的容量 int totalCargo; // 总货物量 // 输入三艘船的容量和总货物量 for(int i = 0; i < 3; i++) { cin >> ships[i]; } cin >> totalCargo; // 将船只按容量从大到小排序 sort(ships, ships + 3, greater<int>()); int trips = 0; while(totalCargo > 0) { for(int i = 0; i < 3; i++) { if(totalCargo >= ships[i]) { totalCargo -= ships[i]; break; // 每次只选择能装下的最大船 } } trips++; } cout << trips << endl; return 0; }3.2 代码优化思路
上述基础版本可以进一步优化:
- 数学计算替代循环:对于大货物量,可以使用除法减少循环次数
- 更优雅的条件判断:使用更简洁的逻辑处理船只选择
- 输入验证:增加对输入数据的合法性检查
优化后的版本:
#include <iostream> #include <algorithm> using namespace std; int main() { int ships[3]; int totalCargo; // 输入并验证数据 for(int i = 0; i < 3; i++) { cin >> ships[i]; if(ships[i] <= 0) { cout << "船容量必须为正数" << endl; return 1; } } cin >> totalCargo; if(totalCargo <= 0) { cout << 0 << endl; return 0; } sort(ships, ships + 3, greater<int>()); int trips = 0; // 先尽可能用大船 trips += totalCargo / ships[0]; totalCargo %= ships[0]; if(totalCargo > 0) { // 再用中等船 trips += totalCargo / ships[1]; totalCargo %= ships[1]; if(totalCargo > 0) { // 最后用小船 trips += totalCargo / ships[2]; if(totalCargo % ships[2] > 0) { trips++; } } } cout << trips << endl; return 0; }3.3 复杂度分析
- 时间复杂度:优化后的算法从O(n)降低到O(1),因为用数学运算替代了循环
- 空间复杂度:O(1),只使用了固定数量的变量
注意:在实际OJ系统中,输入数据通常是合法的,所以输入验证部分可以省略以提高代码运行速度。但在实际工程中,输入验证是必不可少的。
4. 测试用例设计
为了验证代码的正确性,需要设计全面的测试用例:
4.1 常规测试用例
| 测试用例描述 | 输入(ship1,ship2,ship3,cargo) | 预期输出 |
|---|---|---|
| 所有货物刚好用大船运完 | 5 3 2 25 | 5 |
| 需要组合使用不同船 | 5 3 2 7 | 2 (5+2) |
| 货物量小于最小船 | 5 3 2 1 | 1 |
4.2 边界测试用例
| 测试用例描述 | 输入 | 预期输出 |
|---|---|---|
| 货物量为0 | 5 3 2 0 | 0 |
| 船只容量相同 | 3 3 3 10 | 4 |
| 货物量等于船容量 | 5 3 2 3 | 1 |
4.3 特殊测试用例
| 测试用例描述 | 输入 | 预期输出 |
|---|---|---|
| 大船容量远大于货物量 | 100 5 3 7 | 2 (5+3) |
| 需要所有三艘船组合 | 7 5 3 8 | 2 (5+3) |
5. 常见错误与调试技巧
5.1 新手常见错误
变量未初始化:
int trips; // 错误:未初始化 while(...) { trips++; // 未定义行为 }修正:
int trips = 0; // 正确:初始化为0整数除法处理不当:
trips += totalCargo / ships[0]; // 如果余数不为0,需要额外一趟输入顺序假设错误:
- 不要假设输入船只的容量是按某种顺序排列的
- 应该显式排序或比较
5.2 调试技巧
打印中间结果:
cout << "当前货物量: " << totalCargo << " 已运输次数: " << trips << endl;使用断言验证假设:
#include <cassert> assert(ships[0] >= ships[1] && ships[1] >= ships[2]);测试边界条件:
- 专门测试货物量为0、1的情况
- 测试船只容量相等的情况
5.3 OJ提交注意事项
输入输出格式:
- 严格遵循题目要求的输入输出格式
- 不要输出额外的提示信息
性能考虑:
- 避免使用不必要的循环
- 使用更高效的算法处理大数据量
多测试用例处理:
- 有些题目会要求处理多个测试用例,需要适当修改程序结构
int main() { int T; // 测试用例数量 cin >> T; while(T--) { // 处理每个测试用例的代码 } return 0; }6. 扩展思考与进阶学习
6.1 问题变种
船只使用限制:
- 每艘船有使用次数限制
- 某些船只能在特定条件下使用
时间因素:
- 不同船的速度不同
- 计算最短总运输时间而非最少趟数
成本优化:
- 不同船的运营成本不同
- 在满足运输需求下最小化总成本
6.2 算法进阶
对于更复杂的变种问题,可能需要使用以下算法:
贪心算法:
- 每次选择当前最优的船只
- 不一定能得到全局最优解
动态规划:
- 对于有约束条件的优化问题
- 可以保证得到最优解
回溯算法:
- 尝试所有可能的船只组合
- 适用于小规模问题
6.3 学习资源推荐
C++进阶学习:
- 《C++ Primer》:全面深入的C++教程
- 《Effective C++》:C++最佳实践
算法学习:
- 《算法导论》:经典算法教材
- LeetCode:在线算法练习平台
OJ系统:
- 东华OJ:更多本校题目
- Codeforces:国际编程竞赛平台
对于想要进一步提升编程能力的同学,建议从简单题目开始,逐步挑战更复杂的问题。每解决一个问题后,思考是否有更好的解决方法,并尝试实现不同的解法。这种练习方式能快速提高编程能力和算法思维。