在快乐小学一年级(1)班的教室里,Alice同学正面临一个甜蜜的烦恼——她想在三位同学中选择一位最合适的朋友。这个看似简单的选择背后,其实蕴含着有趣的编程逻辑。题目要求我们编写一个C++程序,帮助Alice根据特定规则找到最匹配的朋友。
核心规则可以归纳为:
这个实际问题很好地转化为了一个典型的"最近邻搜索"编程问题,非常适合作为GESP一级认证的考核题目。它不仅考察基础编程能力,还训练学生将生活问题抽象为算法思维的能力。
程序首先需要接收四个整数输入,分别代表Alice和三位同学的身高。在C++中,我们可以使用cin语句实现:
cpp复制int H_Alice, H1, H2, H3;
cin >> H_Alice >> H1 >> H2 >> H3;
这里需要注意变量命名的清晰性。虽然原题使用H1-H4,但更建议使用有意义的名称如H_Alice、H_friend1等,提高代码可读性。
解决这个问题的算法可以形象地称为"打擂台"算法,其核心步骤如下:
这种算法的时间复杂度是O(n),对于小规模数据非常高效。
计算身高差时需要用到绝对值运算,在C++中有两种实现方式:
方法一:条件判断法
cpp复制int diff = H_Alice - H_friend;
if(diff < 0) diff = -diff;
方法二:使用abs函数
cpp复制#include <cmath>
int diff = abs(H_Alice - H_friend);
对于初学者,理解方法一更有助于掌握绝对值的概念,而方法二则更为简洁专业。
下面我们详细分析一个完整的实现方案,并解释每行代码的作用:
cpp复制#include <iostream>
using namespace std;
int main() {
// 1. 输入数据
int Alice, f1, f2, f3;
cin >> Alice >> f1 >> f2 >> f3;
// 2. 初始化最佳朋友候选和最小差距
int best_friend = f1;
int min_diff = Alice - f1;
if(min_diff < 0) min_diff = -min_diff;
// 3. 检查第二位同学
int current_diff = Alice - f2;
if(current_diff < 0) current_diff = -current_diff;
if(current_diff < min_diff ||
(current_diff == min_diff && f2 < best_friend)) {
best_friend = f2;
min_diff = current_diff;
}
// 4. 检查第三位同学
current_diff = Alice - f3;
if(current_diff < 0) current_diff = -current_diff;
if(current_diff < min_diff ||
(current_diff == min_diff && f3 < best_friend)) {
best_friend = f3;
}
// 5. 输出结果
cout << best_friend << endl;
return 0;
}
初始化部分:
cpp复制int best_friend = f1;
int min_diff = Alice - f1;
if(min_diff < 0) min_diff = -min_diff;
这里采用了"打擂台"算法的经典初始化方式,将第一个同学设为初始最佳选择,并计算初始的身高差距。
比较逻辑部分:
cpp复制if(current_diff < min_diff ||
(current_diff == min_diff && f2 < best_friend))
这个条件判断是算法的核心,实现了题目要求的两个规则:
错误1:忽略负值情况
cpp复制int diff = Alice - friend; // 未处理负值
这会导致计算结果错误,必须加上绝对值处理。
错误2:条件判断顺序错误
cpp复制if(f2 < best_friend || current_diff == min_diff) // 逻辑错误
这样的顺序会导致优先比较身高而非差距,违背题目要求。
错误3:忘记更新最小差距
cpp复制if(current_diff < min_diff) {
best_friend = f2;
// 遗漏 min_diff = current_diff;
}
这会导致后续比较使用错误的min_diff值。
使用小规模测试数据验证边界情况:
添加临时输出语句检查中间结果:
cpp复制cout << "Comparing with friend2: diff=" << current_diff << endl;
当前代码对每位同学重复了相似的操作,当同学数量增多时会变得冗长。可以使用数组和循环优化:
cpp复制int friends[3]; // 存储三位同学身高
// 输入省略...
int best_friend = friends[0];
int min_diff = abs(Alice - friends[0]);
for(int i = 1; i < 3; i++) {
int current_diff = abs(Alice - friends[i]);
if(current_diff < min_diff ||
(current_diff == min_diff && friends[i] < best_friend)) {
best_friend = friends[i];
min_diff = current_diff;
}
}
如果班级人数增加到N人,只需调整数组大小和循环次数即可。这种通用性设计体现了良好的编程习惯。
这个问题可以有多种变体,例如:
这些变体只需调整比较逻辑即可实现。
这道题目虽然简单,但涵盖了GESP一级考试的多个核心考点:
对于初学者,理解并掌握这个问题的解法,可以为后续学习更复杂的算法打下坚实基础。特别是"打擂台"算法思想,在查找极值、排序等场景中都有广泛应用。
对于教师或自学者,建议按照以下步骤教学:
对于想进一步提高的学生,可以尝试:
这道题目看似简单,但深入挖掘可以发现很多编程学习的关键点。通过这样的练习,学生不仅能掌握基础语法,更能培养计算思维和问题解决能力。