PAT 1095 Cars on Campus C++版
1.题意
给出校园进出车辆的时间以及牌照信息。接着输入查询的时间,让你输出在这个时刻有多少车辆在校园,最后输出一天中停留在校园最久的车子,如果有多辆车停留的时间相同,那么就按照字母顺序输出其牌照信息,然后输出停留的时间。
2.分析
主要的实现步骤如下:
- step 1:用一个结构体存储车辆的信息
- step 2:将车辆进出入的时间转换成当它的秒数存储;将
in/out
使用0/1
存储 - step 3:因为查询的时间是单调递增的,所以我们可以使用一个小技巧用于避免重复for循环
- step 4:使用两边
sort
将整个结构体排序,第一次是用于筛选出合格的进出车辆信息,并找出停留时间的车辆信息;第二次排序是按照车辆行为的时刻信息,用于找出查询时刻校园中有多少车辆。 - step 5:关于找出某个时刻校园的车辆信息,这里使用了一个变量
count
,如果有一辆车在queryTime
之前进来了,则count++,如果在queryTime
之前出去了,则count--
,最后只需要输出count即可。
具体实现,见如下代码。
3.代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<iostream>
#define maxn 10005
using namespace std;
struct Car{
string plate;//车牌号
int hour;
int min;
int sec;
int flag;//0=in ;1=out
int time = 0;//表示该点刻的时间
int isPair = 0;//标志是否是匹配
};
Car car[maxn];//所有车辆
Car valCar[maxn];//有效的出入车辆
//根据时分秒得到该天的秒数
int getSec(int hour,int min,int sec){
return hour * 3600 + min * 60 + sec;
}
void printTime(int sec){
int tempSec = sec % 60;//取秒
sec /= 60;
int tempMin = sec % 60;
sec /=60;
int tempHour = sec;
printf("%02d:%02d:%02d\n",tempHour,tempMin,tempSec);
}
//根据车牌号,时间排序
int cmp1(Car c1,Car c2){
if(c1.plate == c2.plate) {
return c1.time < c2.time;
}
return c1.plate < c2.plate;
}
//根据时间,车牌号排序
int cmp2(Car c1,Car c2){
if(c1.time == c2.time) {
return c1.plate < c2.plate;
}
return c1.time < c2.time;
}
int main(){
int N,K;
cin >> N >> K;
int i,j;
int tempHour,tempMin,tempSec;
string tempFlag;
int index = 0;//表示有效的信息的下标
for(i = 0;i< N;i++){
cin >> car[i].plate;
scanf("%d:%d:%d",&car[i].hour,&car[i].min,&car[i].sec);
cin >> tempFlag;
if(tempFlag.compare("in") == 0) car[i].flag = 0;
else car[i].flag = 1;
car[i].time = getSec(car[i].hour,car[i].min,car[i].sec);//得到该天的秒数
}
sort(car,car+N,cmp1);//按照车牌号,时间排序
//过滤杂数据
for(i = 0;i< N;i++){
if(car[i].plate.compare(car[i+1].plate) == 0 && car[i].flag == 0
&& car[i+1].flag == 1){//如果车牌号能够对应
//并且是出去的车辆则匹配成功
car[i].isPair = 1;
car[i+1].isPair = 1;
valCar[index++] = car[i];//赋值结构体
valCar[index++] = car[i+1];//赋值结构体
i++;
}
else {
car[i].isPair = 0;//表示没有匹配成功
}
}
//测试输出
// cout <<"------过滤后-----\n";
//1.计算停留时间最久的车牌
set<string> res;
int maxTime = 0;
string curPlate=valCar[0].plate ;//初始值为第一个车牌号
int currSum = 0;//当前每辆车的最长时间
for(i = 0;i< index; i+=2){//每次处理2辆车
currSum += (valCar[i+1].time - valCar[i].time);
if(curPlate.compare(valCar[i+2].plate) != 0){//如果和下2个车牌号不同
if(currSum > maxTime){
res.clear();
res.insert(curPlate);
maxTime = currSum;//重置maxTime
}
else if(currSum == maxTime){
res.insert(curPlate);
}
curPlate = valCar[i+2].plate;//更新车牌号
currSum = 0;//重置
}
}
sort(valCar,valCar+index,cmp2);//根据时间排序
//测试输出
// for(i = 0;i< index; i++){
// cout << valCar[i].plate <<" "<< valCar[i].time <<
// " "<<valCar[i].flag<< " "<<valCar[i].isPair<<"\n";
// }
int preI = 0;//初始化 preI
int queryTime; //查询的时间
int count = 0;//寻找每个时刻的车辆数
while(K--){//当仍未处理完全
scanf("%d:%d:%d",&tempHour,&tempMin,&tempSec);//输入时间,分钟,秒
queryTime = getSec(tempHour,tempMin,tempSec);
for(i = preI ;i < index; i++){//每次检查两条数据
if(valCar[i].time > queryTime){
preI = i; //记录本次结束的时间
break;
}
if(valCar[i].time <= queryTime && valCar[i].flag == 0){
count ++;
}
else if(valCar[i].time <= queryTime && valCar[i].flag == 1){
count --;
}
}
cout << count <<"\n";
}
for(set<string> ::iterator it = res.begin();it!=res.end();it++){
cout << *it <<" ";
}
printTime(maxTime);
}
4.测试用例
16 7
JH007BD 18:00:01 in
ZD00001 11:30:08 out
DB8888A 13:00:00 out
ZA3Q625 23:59:50 out
ZA133CH 10:23:00 in
ZD00001 04:09:59 in
JH007BD 05:09:59 in
ZA3Q625 11:42:01 out
JH007BD 05:10:33 in
ZA3Q625 06:30:50 in
JH007BD 12:23:42 out
ZA3Q625 23:55:00 in
JH007BD 12:24:23 out
ZA133CH 17:11:22 out
JH007BD 18:07:01 out
DB8888A 06:30:50 in
05:10:00
06:30:50
11:00:00
12:23:42
14:00:00
18:00:00
23:59:00
4 1
ZA3Q625 23:59:50 out
ZA3Q625 11:42:00 out
ZA3Q625 06:30:50 out
ZA3Q625 23:55:00 in
05:10:00
4 1
ZA3Q625 23:59:50 out
ZA3Q625 11:42:00 out
ZA3Q625 06:30:50 in
ZA3Q625 23:55:00 in
05:10:00
2 1
ZA3Q625 23:59:59 out
ZA3Q625 00:00:00 in
05:10:00
针对测试用例,我讲一个坑点:
- 不匹配的in或者out信息,都需要删除掉。【笔者之前的代码只删除了不匹配的in信息,导致浪费了几次提交机会,(⊙︿⊙)】