枚举所有学生对,检查三科分差都不超过 5 且总分差不超过 10。
OJ: luogu
题目 ID: P5728
难度:入门
标签:枚举模拟列表python
日期: 2026-07-15 18:44
题意
给出 N 名同学的语文、数学、英语成绩。若一对同学满足:
- 每一科成绩差都不超过
5; - 总分差不超过
10;
则这对同学是“旗鼓相当的对手”。求这样的学生对数量。
思路
N <= 1000,枚举所有无序学生对 i < j 即可。
为了检查总分差,读入每个学生时顺手计算总分,并把四个数存成:
text
(语文, 数学, 英语, 总分)枚举一对学生时,先检查三科分差。如果有一科超过 5,这一对不合法。三科都满足后,再检查总分差是否不超过 10。
这题的正解就是按定义枚举所有学生对,不创建额外 brute.py。
Python 知识
/home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md:多行三整数输入使用map(int, input().split())。/home/rainboy/mycode/hugo-blog/content/program_language/python/brute_force_validation.md:for i in range(n)与for j in range(i + 1, n)枚举无序点对。- 元组
(chinese, math, english, total)可以把一个学生的信息打包保存。 abs(a - b)计算分差的绝对值。
代码
python
n = int(input())
students = []
for _ in range(n):
chinese, math, english = map(int, input().split())
total = chinese + math + english
students.append((chinese, math, english, total))
answer = 0
for i in range(n):
for j in range(i + 1, n):
ok = True
for subject in range(3):
if abs(students[i][subject] - students[j][subject]) > 5:
ok = False
break
if ok and abs(students[i][3] - students[j][3]) <= 10:
answer += 1
print(answer)cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-27 00:00
* update_at: 2026-07-27 00:00
*/
#include <bits/stdc++.h>
using namespace std;
int ch[1005]; // 语文成绩
int ma[1005]; // 数学成绩
int en[1005]; // 英语成绩
int tot[1005]; // 总分
int n, ans;
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> ch[i] >> ma[i] >> en[i];
tot[i] = ch[i] + ma[i] + en[i];
}
// 枚举所有学生对 i < j
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
// 三科分差都不超过 5,且总分差不超过 10
if (abs(ch[i] - ch[j]) <= 5 &&
abs(ma[i] - ma[j]) <= 5 &&
abs(en[i] - en[j]) <= 5 &&
abs(tot[i] - tot[j]) <= 10) {
ans++;
}
}
}
cout << ans;
return 0;
}Pythonic 写法
Python 没有 Haskell 的 $ / 管道运算符,可以用轻量 pipe 把上一步结果传给下一步:
students读入成绩;combinations(..., 2)生成所有学生对;sum(is_opponent(...))统计满足条件的对数。
判断条件单独写成 is_opponent,避免括号嵌套:
python
from itertools import combinations
def pipe(x, *fs):
for f in fs:
x = f(x)
return x
def is_opponent(x, y):
return all(abs(a - b) <= 5 for a, b in zip(x, y)) and abs(sum(x) - sum(y)) <= 10
n = int(input())
students = [tuple(map(int, input().split())) for _ in range(n)]
answer = pipe(
students,
lambda xs: combinations(xs, 2),
lambda pairs: sum(is_opponent(x, y) for x, y in pairs),
)
print(answer)复杂度
共有
总结
这题的关键是枚举“不重复的一对学生”,也就是只枚举 i < j。每对学生按题面条件逐项检查即可。