PAT甲级 1025 Ranking
题目输入
line1 : num_loc(考场个数)
line2 : num_tInloc (第i个考场学生数)
line3 ~( num_tInloc + 3) :
id(考号),score(考生成绩)
(重复以上line2~line( num_tInloc + 3) 格式)
要求输出
line1 : num_testees (总考生数)
line2~(num_testees + 1):
id(考号),rank_all (总排名),id_loc(考场号),rank_loc(考场排名)
代码示例
文件“A1025 Ranking.h”
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
struct Testee {
char id[14];
int score;
int rank_all;
int id_loc; //id of location
int rank_loc; //rank in location
};
#define Comparator(testee1, testee2) ( (testee1.score != testee2.score) ? testee2.score > testee1.score : testee1.id < testee2.id) //first rank by score, second by id (ascending)!
#define GetRankInL(testee1, testee2, rank) ( (testee1.score == testee2.score) ? testee2.rank_loc : rank)
#define GetRankALL(testee1, testee2, rank) ( (testee1.score == testee2.score) ? testee2.rank_all : rank)
//function: comparator
bool cmp(Testee t2, Testee t1) {// sort 默认从参数表后往前赋值
return Comparator(t1, t2); //返回true则swap, 返回false则keep
}
void Ranking() {
int num_loc = 0, num_tInloc = 0; //number of locations, number of testees in one location
vector<Testee> testeesAll; //testees
//input num_loc
scanf("%d", &num_loc);
//then in each location
for (int id_loc = 1; id_loc <= num_loc; id_loc++) {
//input testees information
scanf("%d", &num_tInloc); //number of testees in a location
vector<Testee> testeesInL(num_tInloc);
for (int id = 0; id < num_tInloc; id++) {
scanf("%s %d", &testeesInL[id].id, &testeesInL[id].score); //get id & score
testeesInL[id].id_loc = id_loc; //get id of location
}
//rank by each location
sort( testeesInL.begin(), testeesInL.end(), cmp); //STL内置超级混合排序
testeesInL[0].rank_loc = 1; //set rank_loc
testeesAll.push_back(testeesInL[0]); //first testee in testeesAll (can improve) otherwise it will out of rangge
for (int index = 1; index < num_tInloc; index++) {
testeesInL[index].rank_loc = GetRankInL(testeesInL[index], testeesInL[index - 1], index + 1); //get rank_loc
testeesAll.push_back( testeesInL[index] ); //each testee in testeesAll
}
}
//rank by all
sort(testeesAll.begin(), testeesAll.end(), cmp); //超级混合排序
testeesAll[0].rank_all = 1; //set first rank_all
for (int index = 1; index < testeesAll.size(); index++)
testeesAll[index].rank_all = GetRankALL(testeesAll[index], testeesAll[index - 1], index + 1); //get rank_all
//output
printf("%d\n", testeesAll.size()); //num_testees
for (int id = 0; id < testeesAll.size(); id++) { //testees information
printf("%s %d %d %d\n", testeesAll[id].id, testeesAll[id].rank_all,
testeesAll[id].id_loc, testeesAll[id].rank_loc);
}
}
int main() {
Ranking();
return 0;
}
注意
- 栈溢出
#define CAPACITY 30010
int main(){
Testee testees[CAPACITY]; //错误,会导致栈溢出
return 0;
}
- 原理:
栈区(stack)— 类似于DSA中栈,是由编译器自动分配释放的存储空间 ,存放函数的参数值,局部变量的值等。在Windows下,栈是向低地址扩展的一块连续的大小固定的内存(约1M)。如果申请的空间超过栈的剩余空间时,将提示overflow。
因此必须使用堆(heap) ——类似链表,一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。堆是向高地址扩展的数据结构,是不连续的大小可变的内存区域。
- 字符缺少
string id;
scanf("%s", &testeesInL[id].id); //输入大小为13的string, 只获取了10个
暂时解决
char id[14]; //要加一个空间给结束标志'\0'
scanf("%s", &testeesInL[id].id);
此处理可能导致部分测试不通过,但我不想换成 int64_t 太费内存了
- sort( iterator1, iterator2, compare)
-
sorrt()函数——一道面试深坑
STL的sort算法,数据量大时采用QuickSort快排算法,分段归并排序。一旦分段后的数据量小于某个门槛(16),为避免QuickSort快排的递归调用带来过大的额外负荷,就改用Insertion Sort插入排序。如果递归层次过深,还会改用HeapSort堆排序。
其中给compare( arg2 , arg1 )的传参顺序为从后往前:iterator1—>arg1, iterator2—>arg2,
- 边界问题
-
出现 out of range 大概率vector越界或者vector元素为零,注意下标是否取越界!
-
边界取值在下标和元素个数切换时,最好做好命名,下标用index, 元素用id