题解:洛谷 P5728 旗鼓相当的对手

【题目来源】

洛谷:P5728 【深基5.例5】旗鼓相当的对手 - 洛谷

【题目描述】

现有 \(N\) 名同学参加了期末考试,并且获得了每名同学的信息:语文、数学、英语成绩(均为不超过 \(150\) 的自然数)。如果某对学生 <\(i,j\)> 的每一科成绩的分差都不大于 \(5\),且总分分差不大于 \(10\),那么这对学生就是“旗鼓相当的对手”。现在想知道这些同学中,有几对“旗鼓相当的对手”?同样一个人可能会和其他好几名同学结对。

【输入】

第一行一个正整数 \(N\)

接下来 \(N\) 行,每行三个整数,其中第 \(i\) 行表示第 \(i\) 名同学的语文、数学、英语成绩。最先读入的同学编号为 \(1\)

【输出】

输出一个整数,表示“旗鼓相当的对手”的对数。

【输入样例】

3 90 90 90 85 95 90 80 100 91

【输出样例】

2

【核心思想】

  1. 问题分析:给定 \(N\) 名学生的语文、数学、英语成绩,需要统计有多少对学生满足:每门学科的分差都不大于 5,且总分分差不大于 10。本质是一个枚举所有组合并进行条件判断的问题,由于 \(N\) 通常不大,直接使用双重循环即可。

  2. 算法选择

    • 双重循环枚举:遍历所有学生组合 \((i, j)\)\(1 \le i < j \le N\)),对每对组合检查四个条件(三科分差 \(\le 5\) 且总分分差 \(\le 10\))。时间复杂度 \(O(N^2)\),对于 \(N \le 1000\) 是完全可以接受的。
    • 数据结构优化(可选):如果需要处理更大的 \(N\),可以尝试按总分排序后使用双指针,但本题数据范围下双重循环是最直接且足够高效的方案。
  3. 关键步骤

    • 读入与存储:读取 \(N\),并用三个数组 yushuyin 分别存储每名学生的三科成绩,同时计算总分存入 sum 数组。
    • 枚举组合:外层循环 \(i\)\(1\)\(N\),内层循环 \(j\)\(i+1\)\(N\)
    • 条件判断:使用 abs() 函数计算绝对差,检查:
      • abs(yu[i] - yu[j]) <= 5
      • abs(shu[i] - shu[j]) <= 5
      • abs(yin[i] - yin[j]) <= 5
      • abs(sum[i] - sum[j]) <= 10
    • 计数与输出:若所有条件满足,则 ans++;最后输出 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N^2)\)\(N\) 通常 \(\le 1000\),可接受。
    • 空间复杂度:\(O(N)\),用于存储成绩和总分。
  5. 模拟与枚举

    • 组合枚举:使用 \(i\)\(1\)\(N\)\(j\)\(i+1\)\(N\) 的方式,可以避免重复计数(每对只计算一次)。
    • 多条件判断:所有条件必须同时满足,因此使用逻辑与(&&)连接。
    • 绝对差计算:使用 abs() 函数可以简洁地判断差值的绝对值是否在范围内。
    • 适用场景:这类“统计满足多重条件的配对数量”问题,在数据规模较小时,双重循环是最直接、最可靠的解决方法。

【算法标签】

入门 #模拟

【代码详解】

#include <bits/stdc++.h>  // 包含标准库头文件(万能头文件)
using namespace std;      // 使用标准命名空间

/**
 * 主函数 - 程序入口
 * @return 程序执行状态码(0表示成功)
 */
int main()
{
    int n;               // 定义变量:学生人数
    int yu[1005];        // 定义数组:存储语文成绩
    int shu[1005];       // 定义数组:存储数学成绩
    int yin[1005];       // 定义数组:存储英语成绩
    int sum[1005];       // 定义数组:存储总分
    int ans = 0;         // 定义变量:符合条件的对手对数

    cin >> n;            // 输入学生人数

    // 输入每个学生的三科成绩并计算总分
    for (int i = 1; i <= n; i++)
    {
        cin >> yu[i] >> shu[i] >> yin[i];
        sum[i] = yu[i] + shu[i] + yin[i];
    }

    // 遍历所有学生组合,统计符合条件的对手对数
    for (int i = 1; i <= n; i++)
    {
        for (int j = i + 1; j <= n; j++)
        {
            // 旗鼓相当的对手判定条件:
            // 1. 各科成绩差不超过5分
            // 2. 总分差不超过10分
            if (abs(yu[i] - yu[j]) <= 5 &&
                abs(shu[i] - shu[j]) <= 5 &&
                abs(yin[i] - yin[j]) <= 5 &&
                abs(sum[i] - sum[j]) <= 10)
            {
                ans++;  // 符合条件的对手对数加1
            }
        }
    }

    cout << ans << endl;  // 输出结果

    return 0;             // 程序正常结束
}

【运行结果】

3
90 90 90
85 95 90
80 100 91
2
posted @ 2026-08-30 09:17  团爸讲算法  阅读(7)  评论(0)    收藏  举报