【P5728】旗鼓相当的对手
题目描述
现有 N N N 名同学参加了期末考试,并且获得了每名同学的信息:语文、数学、英语成绩(均为不超过 150 150 150 的自然数)。如果某对学生 < i , j > \text{<}i,j\text{>} <i,j> 的每一科成绩的分差都不大于 5 5 5,且总分分差不大于 10 10 10,那么这对学生就是“旗鼓相当的对手”。现在想知道这些同学中,有几对“旗鼓相当的对手”?同样一个人可能会和其他好几名同学结对。
输入格式
第一行一个正整数 N N N。
接下来 N N N 行,每行三个整数,其中第 i i i 行表示第 i i i 名同学的语文、数学、英语成绩。最先读入的同学编号为 1 1 1。
输出格式
输出一个整数,表示“旗鼓相当的对手”的对数。
样例 #1
样例输入 #1
3
90 90 90
85 95 90
80 100 91
样例输出 #1
2
提示
数据保证, 2 ≤ N ≤ 1000 2 \le N\le 1000 2≤N≤1000 且每科成绩为不超过 150 150 150 的自然数。
由本题可以学到:
1.如何正确打开数组的创建方式
2.数学函数abs&fabs
3.写代码认真点,别犯低级错误
虽然本题在循环结构题单里难度不高,但却是让我卡了最久也没想出来的一个
1.首先是我的思路,题目输入同学数量,和每一个同学对应的三科成绩,首先我想到的是四维数组,即第一个数组代表学生个体,后面三个数组依次代表成绩
但显然这种思想是绝对错误的,这种四维数组不仅麻烦,而且由于n最大可以取到1000,所以四维数组过大,根本无法创建,舍弃掉这种想法后,我又想到另外一种方法,就是开a[1001][3003]
前面代表学生个数,后面依次三个数字代表三个成绩,但这种数组带来的麻烦就是,无法简便的进行对各科成绩的比较,后面越想越烦,便一直没有想出来
2.正确的开数组方式:
如题意,n个同学的三个成绩,我们只需要开n3的数组就完全可以,因为前面的数组是各自不同的,(即a[i]与a[j])
)所以后面3个大小的数组分别存成绩就完全欧克(我当时真心脑抽了),所以开a[1024][4]
就可以了(后面数组长度为4的原因是因为我想直接按顺序把成绩存在1.2.3里面,看着符合逻辑一点,当然其实我最开始开的是[3],这也是后面我debug时出现的问题 )
综上所述:若是要给数据开数组,看数据的名字:例如n个同学的三个成绩,就开n3就行;x个老人的(1个)年龄,开一维就够,y个老师的(1个)年龄和(1个)体重,自然就要2维,具体含义还须个人体会。
3.写code遇到的困难
1.因为分差可能为负数,所以必须对分差做取绝对值操作,但是直接写很麻烦,所以要用abs简化条件判断
abs函数:接收一个整数并返回正值
fabs函数:接受一个浮点数并返回浮点数(前面有个f,即”fu“)
形式为abs()/fabs();
注意其被保存在#include头文件中,在开头需要写出
2。于是我写出了如下代码:
```cpp
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int n;
int j;
cin >> n;
int a[1024][3];
int t = 0;
for (int i = 1; i < n + 1; i++)
{
for (j = 1; j <= 3; j++)
{
cin >> a[i][j];
}
}
for (int i = 1; i < n ; i++)
{
for (int j = 1; j < n + 1; j++)
{
if (abs(a[i][1] - a[j][1]) <= 5
&& abs(a[i][2] - a[j][2]) <= 5
&& abs(a[i][3] - a[j][3]) <= 5
&&abs(a[i][1] - a[j][1]) + abs(a[i][1] - a[j][1]) + abs(a[i][3] - a[j][3]) <= 11)
t++;
}
}
cout << t << endl;
return 0;
}
3.Debug遇到的问题
1.first提交
100%数据WA
for (int i = 1; i < n ; i++)
for (int j = 1; j < n + 1; j++)
发现最后依次进行数据比较的时候,每一个学生都会与第一个学生到最后一个学生进行比较,这样不仅浪费时间,而且自己还会与自己比较,造成每一个学生都会多使t+1,造成数据错误
将代码改为
for (int i = 1; i < n ; i++)
for (int j = i+1; j < n + 1; j++)
即每一个学生只与后面的学生进行比较(因为前面的学生已经与他进行过比较了)
2.second提交
(这回应该没问题了吧)
80%数据WA(我??)
int a[1024][3];
for (j = 1; j <= 3; j++)
检查时,发现前面我只开了长度为3存放成绩的数组(即0,1,2),但是后面为了符合逻辑,我是用的(1,2,3)存放成绩,造成数组越界了;而且存放的数据是不对的
于是改为
int a[1024][4];
3.third提交
(这回肯定万无一失了,简简单单数组越界罢了)
80%数据WA
…
&&abs(a[i][1] - a[j][1]) + abs(a[i][1] - a[j][1]) + abs(a[i][3] - a[j][3]) <= 11)
找了半天,好吧,是我眼瞎,两个都是a[i][1]a[j][1]
于是改为:
&&abs(a[i][1] - a[j][1]) + abs(a[i][2] - a[j][2]) + abs(a[i][3] - a[j][3]) <= 11)
4.fourth提交
来吧!!
80%数据WA…
我**
好吧,居然是判定条件多打了一个等号。。。。
改为:
&&abs(a[i][1] - a[j][1]) + abs(a[i][2] - a[j][2]) + abs(a[i][3] - a[j][3]) <= 10)
5.fifth提交
我命由我不由天!
80%数据WA
我************
苦苦寻找,苦苦寻找,终于我回到了题目:”且总分分差不大于 10“;
再看我的代码:
&&abs(a[i][1] - a[j][1]) + abs(a[i][2] - a[j][2]) + abs(a[i][3] - a[j][3]) <= 10)
mad三次绝对值求和,求出来啥都不是啊!总分分差不就是三个数据相加再求差的绝对值吗?
改为:
&& abs(a[i][1] - a[j][1] + a[i][2] - a[j][2] + a[i][3] - a[j][3]) <= 10)
6.sixth提交
AC!!!
WOLEILE
完整代码:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int n;
int j;
cin >> n;
int a[1024][4];
int t = 0;
for (int i = 1; i < n + 1; i++)
{
for (j = 1; j <= 3; j++)
{
cin >> a[i][j];
}
}
for (int i = 1; i < n ; i++)
{
for (int j = i+1; j < n + 1; j++)
{
if (abs(a[i][1] - a[j][1]) <= 5
&& abs(a[i][2] - a[j][2]) <= 5
&& abs(a[i][3] - a[j][3]) <= 5
&& abs(a[i][1] - a[j][1] + a[i][2] - a[j][2] + a[i][3] - a[j][3]) <= 10)
t++;
}
}
cout << t << endl;
return 0;
}
over--------------------------