题解:洛谷 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

【核心思想】

  1. 问题分析:给定 \(n\) 个小朋友的体重 \(w_i\)(千克)和身高 \(h_i\)(米),计算每个小朋友的 BMI(\(BMI = w_i / h_i^2\)),然后按 BMI 从高到低排序并输出对应的编号。这是一个自定义排序问题,核心在于正确计算 BMI 并维护编号与计算结果的映射关系。

  2. 算法选择

    • 结构体封装:使用结构体存储每个小朋友的 BMI 值和原始编号,保持数据关联性
    • 自定义比较器:定义按 BMI 降序的比较函数,配合排序算法完成排序
  3. 关键步骤

    • 读入数据:读取 \(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\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n \log n)\),计算 BMI 为 \(O(n)\),排序为 \(O(n \log n)\)
    • 空间复杂度:\(O(n)\),存储 \(n\) 个结构体元素
  5. 自定义排序的核心思想

    • 数据与索引绑定:通过结构体将计算值(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
posted @ 2026-07-07 09:13  团爸讲算法  阅读(166)  评论(0)    收藏  举报