题解:洛谷 B4558 身高体重指数
【题目来源】
洛谷:B4558 [GESP202606 四级] 身高体重指数 - 洛谷
【题目描述】
一个人的身高体重指数(BMI)等于其体重(千克为单位)除以其身高(米为单位)的平方。
例如,一个体重为 \(50\text{ kg}\),身高为 \(1.6\text{ m}\) 的人的身高体重指数为 \(50\text{ kg}/1.6\text{ m}/1.6\text{ m} = 19.53125\text{ kg/m}^2\)。
现在有 \(n\) 个小朋友,第 \(i\) 个小朋友的编号为 \(i\),体重为 \(w_i\),身高为 \(h_i\)。
请按照身高体重指数从高到低为小朋友们排序,数据保证不存在两个小朋友的身高体重指数完全相同。输出排序后小朋友的编号。
【输入】
输入 \(3\) 行,
第一行为一个正整数 \(n\),表示小朋友的个数;
第二行为 \(n\) 个整数 \(w_1, w_2, \cdots, w_n\) 表示小朋友们的体重,单位为 \(\text{kg}\);
第三行为 \(n\) 个浮点数 \(h_1, h_2, \cdots, h_n\) 表示小朋友们的身高,单位为 \(\text{m}\)。
【输出】
输出一行 \(n\) 个数,表示按照身高体重指数从高到低排序后的编号。
【输入样例】
3
45 33 39
1.55 1.33 1.44
【输出样例】
3 1 2
【核心思想】
-
问题分析:给定 \(n\) 个小朋友的体重 \(w_i\)(千克)和身高 \(h_i\)(米),计算每个小朋友的 BMI(\(BMI = w_i / h_i^2\)),然后按 BMI 从高到低排序并输出对应的编号。这是一个自定义排序问题,核心在于正确计算 BMI 并维护编号与计算结果的映射关系。
-
算法选择:
- 结构体封装:使用结构体存储每个小朋友的 BMI 值和原始编号,保持数据关联性
- 自定义比较器:定义按 BMI 降序的比较函数,配合排序算法完成排序
-
关键步骤:
- 读入数据:读取 \(n\),以及数组 \(w[1..n]\) 和 \(h[1..n]\)
- 计算 BMI:遍历 \(i\) 从 \(1\) 到 \(n\),\(p[i].b \leftarrow 1.0 \times w[i] / (h[i] \times h[i])\),\(p[i].idx \leftarrow i\)
- 自定义排序:定义比较函数 \(cmp(x, y)\) 返回 \(x.b > y.b\),调用 \(sort\) 对 \(p[1..n]\) 排序
- 输出结果:按排序后的顺序输出 \(p[i].idx\)
-
时间/空间复杂度:
- 时间复杂度:\(O(n \log n)\),计算 BMI 为 \(O(n)\),排序为 \(O(n \log n)\)
- 空间复杂度:\(O(n)\),存储 \(n\) 个结构体元素
-
自定义排序的核心思想:
- 数据与索引绑定:通过结构体将计算值(BMI)与原始编号封装在一起,排序后仍能追溯原始身份,避免排序后丢失对应关系
- 浮点精度处理:使用
1.0 * w[i]将整数除法转为浮点除法,确保 BMI 计算精度;利用题目保证的"不存在两个 BMI 完全相同"避免浮点数比较精度问题 - 比较器设计:返回 \(x.b > y.b\) 实现降序排列,若需升序则改为 \(x.b < y.b\)
- 稳定排序非必需:由于题目保证 BMI 互不相同,无需考虑相等元素的相对顺序,直接使用快速排序即可
- 适用于需要按计算指标排序并保留原始标识信息的基础排序类问题
【算法标签】
普及- #语法基础
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 1005; // 常量:最大小朋友数量
int n; // n: 小朋友个数
int w[N]; // w[i]: 第 i 个小朋友的体重(千克)
double h[N]; // h[i]: 第 i 个小朋友的身高(米)
struct Person // 小朋友结构体,用于存储 BMI 和编号
{
double b; // b: 身高体重指数(BMI)
int idx; // idx: 小朋友的编号
} p[N]; // p[i]: 第 i 个小朋友的信息
bool cmp(Person x, Person y) // 比较函数:按 BMI 从高到低排序
{
return x.b > y.b; // BMI 大的排在前面
}
int main()
{
cin >> n; // 读入小朋友个数
for (int i = 1; i <= n; i++) // 读入 n 个小朋友的体重
cin >> w[i];
for (int i = 1; i <= n; i++) // 读入 n 个小朋友的身高
cin >> h[i];
for (int i = 1; i <= n; i++) // 计算每个小朋友的 BMI 并记录编号
{
p[i].b = 1.0 * w[i] / (h[i] * h[i]); // BMI = 体重 / 身高²
p[i].idx = i; // 记录小朋友编号
}
sort(p + 1, p + n + 1, cmp); // 按 BMI 从高到低排序
for (int i = 1; i <= n; i++) // 输出排序后的编号
cout << p[i].idx << " ";
cout << endl;
return 0;
}
【运行结果】
3
45 33 39
1.55 1.33 1.44
3 1 2
浙公网安备 33010602011771号