为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛。现请你根据比赛结果统计出技术最强的那个学校。
输入格式:
输入在第 1 行给出不超过 105 的正整数 N,即参赛人数。随后 N 行,每行给出一位参赛者的信息和成绩,包括其所代表的学校的编号(从 1 开始连续编号)、及其比赛成绩(百分制),中间以空格分隔。
输出格式:
在一行中给出总得分最高的学校的编号、及其总分,中间以空格分隔。题目保证答案唯一,没有并列。
输入样例:
6
3 65
2 80
1 100
2 70
3 40
3 0
输出样例:
2 150
知识:
using namespace std 引入整个命名空间,不仅仅是iostream
#include <vector> 引入容器
定义vector:
vector<类型> 名字;
向vector对象中添加元素 :
vector的成员函数:push_back,负责把一个值当成vector对象的尾元素压到vector对象的尾端
实时读入数据:
while(cin>>word){
text.push_back(word);
}
size_t类型:malloc、sizeof、strlen 等 返回值也是size_t类型,返回值类型一致,无符号整数,避免溢出
排序方法:
冒泡排序:
for(int i = 0;i<n-1;i++){ //最后一个不用比
for(int j =0;j<n-1-i;j++){ //排好的放在最后
if(vector[j]<vector[j+1]){
swap(vector[j],vector[j+1]);//使用swap交换两者
}
}
}
引入algorithm 库,内含swap函数
思路:
记录输入--->排序--->输出
原代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std
int
main(){
int N;
int n;//记录输入
vector<int> num_score; //学校的编号_比赛成绩,初始化为空vector
cin>>N;//先输入参赛人数
while(cin>>n){
num_score.push_back(n) //压入
}
//根据成绩排序
for(size_t i = 1;i<N-2;i+=2){
for(size_t j = 1;i<N-2-i;j+=2){
if(num_score[j]<num_score[j+2]){
swap(num_score[j],num_score[j+2]);//交换成绩
swap(num_socre[j-1],num_socre[j+2-1]);//学校也得换
}
}
}
//打印最强的
cout<<num_score[0]<<" "<<num_score[1]<<endl;
return 0;
}
放到visual studio里看一下有没有语法错误:
using namespace std要有分号:using namespace std;
while的中文括号
num_score.push_back(n)没写分号
swap(num_socre[j - 1], num_socre[j + 2 - 1]); score打错
修改:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int
main() {
int N;
int n;//记录输入
vector<int> num_score; //学校的编号_比赛成绩,初始化为空vector
cin >> N;//先输入参赛人数
while(cin >> n){
num_score.push_back(n); //压入
}
//根据成绩排序
for (size_t i = 1; i < N - 2; i += 2) {
for (size_t j = 1; i < N - 2 - i; j += 2) {
if (num_score[j] < num_score[j + 2]) {
swap(num_score[j], num_score[j + 2]);//交换成绩
swap(num_score[j - 1], num_score[j + 2 - 1]);//学校也得换
}
}
}
//打印最强的
cout << num_score[0] << " " << num_score[1] << endl;
return 0;
}
第一次测试
a.cpp: In function ‘int main()’:
a.cpp:16:26: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
16 | for (size_t i = 1; i < N - 2; i += 2) {
| ~~^~~~~~~
原因:size_t和int的比较
解决:
size_t N;
第二次测试:
评测详情
测试点 | 提示 | 内存(KB) | 用时(ms) | 结果 | 得分 | |
0 | 300 | 9 | 段错误 | 0 / 12 | ||
1 | 504 | 10 | 段错误 | 0 / 3 | ||
2 | 316 | 10 | 段错误 | 0 / 2 | ||
3 | 1520 | 47 | 段错误 | 0 / 3 |
段错误(Segmentation Fault)通常是由访问无效内存地址引起的
解决方法:不用while(cin>>n),改为for循环
for循环中应该是j<N-2-i
新增的for循环中要先输入再压栈,条件中是<2*N-1,不是2*n-1,注意区分变量
第三次测试:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int
main() {
size_t N;
int n;//记录输入
vector<int> num_score; //学校的编号_比赛成绩,初始化为空vector
cin >> N;//先输入参赛人数
for (int i = 0; i < 2 * N - 1; i++) {
cin >> n;
num_score.push_back(n); //压入
}
//根据成绩排序
for (size_t i = 1; i < N - 2; i += 2) {
for (size_t j = 1; j < N - 2 - i; j += 2) {
if (num_score[j] < num_score[j + 2]) {
swap(num_score[j], num_score[j + 2]);//交换成绩
swap(num_score[j - 1], num_score[j + 2 - 1]);//学校也得换
}
}
}
//打印最强的
cout << num_score[0] << " " << num_score[1] << endl;
return 0;
}
评测详情:多种错误
测试点 | 提示 | 内存(KB) | 用时(ms) | 结果 | 得分 | |
0 | 304 | 2 | 答案错误 | 0 / 12 | ||
1 | 468 | 2 | 答案错误 | 0 / 3 | ||
2 | 404 | 13 | 段错误 | 0 / 2 | ||
3 | 1540 | 200 | 运行超时 | 0 / 3 |
修改:
for循环中i<2*N
最大的问题在于:
for (size_t i = 1; i < N-2; i += 2) {
for (size_t j = 1; j < N -2- i; j += 2) {
if (num_score[j] < num_score[j + 2]) {
swap(num_score[j], num_score[j + 2]);//交换成绩
swap(num_score[j - 1], num_score[j + 2 - 1]);//学校也得换
}
}
}
N不等于输入数据的数量,因为是两个一组输入的,条件出现错误
第四次测试:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int
main() {
size_t N;
int n;//记录输入
vector<int> num_score; //学校的编号_比赛成绩,初始化为空vector
cin >> N;//先输入参赛人数
for (int i = 0; i < 2 * N ; i++) {
cin >> n;
num_score.push_back(n); //压入
}
//根据成绩排序
for (size_t i = 1; i < 2*N-2; i += 2) {
for (size_t j = 1; j <2* N -2- i; j += 2) {
if (num_score[j] < num_score[j + 2]) {
swap(num_score[j], num_score[j + 2]);//交换成绩
swap(num_score[j - 1], num_score[j + 2 - 1]);//学校也得换
}
}
}
//打印最强的
cout << num_score[0] << " " << num_score[1] << endl;
return 0;
}
评测详情
测试点 | 提示 | 内存(KB) | 用时(ms) | 结果 | 得分 | |
0 | 304 | 2 | 答案错误 | 0 / 12 | ||
1 | 484 | 2 | 答案错误 | 0 / 3 | ||
2 | 408 | 3 | 答案正确 | 2 / 2 | ||
3 | 1876 | 200 | 运行超时 | 0 / 3 |
修改:
题读错了,要求返回的是最强的学校及总得分
转变思路:
由对程序进行排序转换为对学校序号进行排序,成绩随着学校序号一起交换,然后对学校学号相同的成绩进行累加,再次对成绩累加
第四次测试:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int
main() {
size_t N;
int n;//记录输入
vector<int> num_score; //学校的编号_比赛成绩,初始化为空vector
cin >> N;//先输入参赛人数
for (int i = 0; i < 2 * N; i++) {
cin >> n;
num_score.push_back(n); //压入
}
//对学校序号排序
for (int i = 0; i < 2 * N - 3; i += 2) {
for (int j = 0; j < 2 * N - 3 - i; j += 2) {
if (num_score[j] < num_score[j + 2]) {
swap(num_score[j] , num_score[j + 2]);
swap(num_score[j + 1] , num_score[j + 2 + 1]);
}
}
}
//对学校序号相同的成绩进行累加
for (int i = 1; i < 2 * N - 2; i += 2) {
for (int j = 1; j < 2 * N - j; j += 2) {
if (num_score[i - 1] == num_score[i + j]) {
num_score[i] += num_score[i + j + 1];
}
else if (num_score[i - 1] != num_score[i + j]) {
i += j-2;
break;
}
}
}
//根据成绩排序
for (size_t i = 1; i < 2 * N - 2; i += 2) {
for (size_t j = 1; j < 2 * N - 2 - i; j += 2) {
if (num_score[j] < num_score[j + 2]) {
swap(num_score[j], num_score[j + 2]);//交换成绩
swap(num_score[j - 1], num_score[j + 2 - 1]);//学校也得换
}
}
}
//打印最强的
cout << num_score[0] << " " << num_score[1] << endl;
return 0;
}
评测详情
测试点 | 提示 | 内存(KB) | 用时(ms) | 结果 | 得分 | |
0 | 304 | 2 | 答案正确 | 12 / 12 | ||
1 | 468 | 3 | 答案错误 | 0 / 3 | ||
2 | 300 | 10 | 段错误 | 0 / 2 | ||
3 | 1520 | 200 | 运行超时 | 0 / 3 |
用了三个双重循环,仍然报错,代码复杂
原因分析:
经测试,当输入N=1时会报段错误
而N等于2时不会
可设置if语句
第五次测试
评测详情
测试点 | 提示 | 内存(KB) | 用时(ms) | 结果 | 得分 | |
0 | 304 | 2 | 答案正确 | 12 / 12 | ||
1 | 432 | 2 | 答案错误 | 0 / 3 | ||
2 | 396 | 3 | 答案正确 | 2 / 2 | ||
3 | 1612 | 200 | 运行超时 | 0 / 3 |
果然段错误是因为N=1,现在考虑答案错误的情况
在每个双重循环下加入
for (int i = 0; i < 2 * N; i++) {
cout <<"first/sec/third" << num_score[i] << endl;
}
f/s/t分别代表三次循环,结果如下
可以看到,最终排序是1 100的位置再最后,说明没有进行排序,也就是问题所在
修改:
for (size_t i = 1; i < 2 * N - 2; i += 2) {
for (size_t j = 1; j < 2 * N - 2; j += 2) {
if (num_score[j] < num_score[j + 2]) {
swap(num_score[j], num_score[j + 2]);//交换成绩
swap(num_score[j - 1], num_score[j + 2 - 1]);//学校也得换
}
}
}
将j循环中2*N-i换成2*N,问题解决
测试结果
评测详情
测试点 | 提示 | 内存(KB) | 用时(ms) | 结果 | 得分 | |
0 | 308 | 2 | 答案正确 | 12 / 12 | ||
1 | 488 | 2 | 答案错误 | 0 / 3 | ||
2 | 492 | 2 | 答案正确 | 2 / 2 | ||
3 | 1520 | 200 | 运行超时 | 0 / 3 |
学习:
#include <iostream>
using namespace std;
int main(){
int N;
int m=0;
int a[100001]={0};
cin>>N;
int n,s;
while(N--){
cin>>n>>s;
a[n]+=s;
if(a[n]>=a[m]){
m=n;
}
}
cout<<m<<" "<<a[m]<<endl;
}
评测详情
测试点 | 提示 | 内存(KB) | 用时(ms) | 结果 | 得分 | |
0 | 688 | 3 | 答案正确 | 12 / 12 | ||
1 | 868 | 2 | 答案正确 | 3 / 3 | ||
2 | 872 | 3 | 答案正确 | 2 / 2 | ||
3 | 900 | 39 | 答案正确 | 3 / 3 |