题目重现:
“一帮一学习小组”是中小学中常见的学习组织方式,老师把学习成绩靠前的学生跟学习成绩靠后的学生排在一组。本题就请你编写程序帮助老师自动完成这个分配工作,即在得到全班学生的排名后,在当前尚未分组的学生中,将名次最靠前的学生与名次最靠后的异性学生分为一组。
输入格式:
输入第一行给出正偶数N
(≤50),即全班学生的人数。此后N
行,按照名次从高到低的顺序给出每个学生的性别(0代表女生,1代表男生)和姓名(不超过8个英文字母的非空字符串),其间以1个空格分隔。这里保证本班男女比例是1:1,并且没有并列名次。
输出格式:
每行输出一组两个学生的姓名,其间以1个空格分隔。名次高的学生在前,名次低的学生在后。小组的输出顺序按照前面学生的名次从高到低排列。
输入样例:
8
0 Amy
1 Tom
1 Bill
0 Cindy
0 Maya
1 John
1 Jack
0 Linda
输出样例:
Amy Jack
Tom Linda
Bill Maya
Cindy John
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
实现思路:
实现这个题目的核心思路在于:
-
数据组织:利用结构体数组来组织和存储学生的信息,包括性别和姓名。数组的索引自然映射学生的排名顺序,简化后续的配对逻辑处理。
-
异性配对原则:基于题目要求,采取从高排名到低排名的策略,每次选取当前最高排名的学生,为其寻找一个最低排名且性别相反的伴侣。这样确保了配对的最优性和异性原则。
-
避免重复配对:通过修改已配对学生的性别标记(例如,将其标记为2),确保每位学生只能参与一次配对,防止重复匹配,这是保证算法正确性的关键所在。
关键代码:
for(int j = 0; j < (x/2); j++)
{
for(int n = 0; n < (x/2); n++)
{
if(student[j].sex+student[x-1-n].sex==1)
{
// 关键操作1: 确认性别互补(一男一女),准备进行配对
student[x-1-n].sex=2;
// 关键操作2: 输出配对的学生姓名,完成一组配对
cout<<student[j].name<<' '<<student[x-1-n].name<<endl;
break;
}
}
}
这段代码的关键点在于:
- 外层循环变量
j
用于遍历排名靠前的学生。 - 内层循环变量
n
用于遍历排名靠后的学生,并尝试为当前的j
找到合适的异性配对。 - 条件判断
if(student[j].sex+student[x-1-n].sex==1)
确保正在进行配对的学生性别互补(一个为0,一个为1,代表一男一女)。 - 性别标记修改
student[x-1-n].sex=2;
避免已经配对的学生被再次配对。 - 输出配对结果 使用
cout
输出配对成功的两名学生姓名,完成一组配对的输出
通过截图:
完整代码:
#include <iostream>
using namespace std;
// 定义一个结构体来存储学生的性别和姓名
struct class1 {
int sex; // 学生性别,0代表女生,1代表男生
char name[100]; // 学生姓名
};
int main() {
int x; // 学生总人数
cin >> x;
// 动态创建结构体数组,用于存储所有学生的信息
struct class1* student = new class1[x];
// 输入学生信息,包括性别和姓名
for(int i = 0; i < x; i++) {
cin >> student[i].sex >> student[i].name;
}
// 遍历前一半的学生(排名高的学生)
for(int j = 0; j < x/2; j++) {
// 再遍历后一半的学生(排名低的学生),寻找与当前高排名学生性别的补充(异性)
for(int n = 0; n < x/2; n++) {
// 检查当前高排名学生与低排名学生的性别是否为异性(一男一女)
if(student[j].sex + student[x-1-n].sex == 1) {
// 如果是异性,标记低排名学生为已配对(这里通过改变性别标记为2实现,实际上可以使用更优雅的方式)
student[x-1-n].sex = 2;
// 输出配对成功的两名学生姓名
cout << student[j].name << ' ' << student[x-1-n].name << endl;
// 配对成功后跳出内层循环,寻找下一位排名靠前的学生
break;
}
}
}
// 释放动态分配的内存
delete[] student;
return 0;
}