这一题基本算是PAT里面最难的排序题,它需要考虑的问题非常多。例如从一开始的结构体的设置,是应该考虑用record记录,还是用car存储信息,然后就会意识到后面要比较query的时间,还是用record记录比较方便。同时可以用map数据类型来存储car所停放的时间。
算法步骤:
- 建立结构体
- 编写比较函数,分别比较record时间和car停放时间
- 编写时间转换函数(用于比较时间)
- 将输入数据存储到record数组中
- 对record数组进行排序
- 筛选符合条件的出入时间对,获取car最长停放时间
- 将record按时间顺序排序
- 获取query时间点前的car的停放数量
- 根据car最长停放时间,输出相应的车牌号
关键点:
- 选择合适的结构体
- 比较时间的时候最好把时间统一转换成以秒为单位
- 筛选符合条件的时间对
- 存放car的停放时间最好使用map数据类型
- 获取car的停放数量这里容易写超时,最好还是通过时间排序的record获取停放数量
核心代码:
- 筛选符合条件的时间对
for (int i = 0; i < n-1;i++){
if(strcmp(records[i].plateNumber,records[i+1].plateNumber)==0
&& records[i].status==1&&records[i+1].status==2){
validRecord[cnt++] = records[i];
validRecord[cnt++] = records[i+1];
if(parktime.count(records[i].plateNumber)==0){
parktime[records[i].plateNumber] = 0;
}
parktime[records[i].plateNumber] += (records[i+1].time - records[i].time);
maxTime = max(maxTime, parktime[records[i].plateNumber]);
}
}
- 通过时间排序的record获取停放数量
for (int i = 0; i < k;i++){
int hh, mm, ss;
scanf("%d:%d:%d", &hh, &mm, &ss);
int timeQuery = timeToInt(hh, mm, ss);
//这里如果不选用这个方法,很容易超时
while(index<cnt && validRecord[index].time<=timeQuery){
if(validRecord[index].status==1){
carNumber++;
}else{
carNumber--;
}
index++;
}
printf("%d\n", carNumber);
}
核心代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
map<string, int> parktime;
struct record{
char plateNumber[8];
int time;
int status;
} records[10010],validRecord[10010];
bool cmpRecord(record a,record b){
int s = strcmp(a.plateNumber, b.plateNumber);
if(s!=0){
return s < 0;
}else{
return a.time < b.time;
}
}
bool cmpValid(record a,record b){
return a.time < b.time;
}
int timeToInt(int hh,int mm,int ss){
return hh * 3600 + mm * 60 + ss;
}
int main(){
int n, k;
scanf("%d %d", &n, &k);
for (int i = 0; i < n;i++){
int hh, mm, ss;
char status[5];
scanf("%s %d:%d:%d %s", records[i].plateNumber, &hh, &mm, &ss, status);
records[i].time = hh * 3600 + mm * 60 + ss;
if(strcmp(status,"in")==0){
records[i].status = 1;
}else{
records[i].status = 2;
}
}
sort(records, records + n, cmpRecord);
// int start = 0;
int cnt = 0;
int maxTime = -1;
for (int i = 0; i < n-1;i++){
if(strcmp(records[i].plateNumber,records[i+1].plateNumber)==0
&& records[i].status==1&&records[i+1].status==2){
validRecord[cnt++] = records[i];
validRecord[cnt++] = records[i+1];
if(parktime.count(records[i].plateNumber)==0){
parktime[records[i].plateNumber] = 0;
}
parktime[records[i].plateNumber] += (records[i+1].time - records[i].time);
maxTime = max(maxTime, parktime[records[i].plateNumber]);
}
}
//按时间排序
sort(validRecord, validRecord + cnt, cmpValid);
//这里在外面声明,就能节省大量的时间
int carNumber = 0;
int index = 0;
for (int i = 0; i < k;i++){
int hh, mm, ss;
scanf("%d:%d:%d", &hh, &mm, &ss);
int timeQuery = timeToInt(hh, mm, ss);
//这里如果不选用这个方法,很容易超时
while(index<cnt && validRecord[index].time<=timeQuery){
if(validRecord[index].status==1){
carNumber++;
}else{
carNumber--;
}
index++;
}
//这是我按照没有排序的validRecord比较时间,会发现很容易超时
// for (int j = 1; j < cnt;j=j+2){
// if(validRecord[j-1].time<=timeQuery && validRecord[j].time>timeQuery){
// carNumber++;
// }
// }
printf("%d\n", carNumber);
}
map<string, int>::iterator it;
for (it = parktime.begin(); it != parktime.end();it++){
if(it->second==maxTime){
printf("%s ", it->first.c_str());
}
}
printf("%02d:%02d:%02d", maxTime / 3600, maxTime % 3600 / 60, maxTime % 60);
}