题目大意
给出浙大门口进出校门的车辆记录,根据这些记录,判断给定时间点校园内有多少辆车,最后给出当天停车最长的车牌号和对应时长。
我的思路
这道题自己硬怼了2h,AC了,好开心~
1. 把题目给的车辆记录存起来,这里用Record结构体,存储:车牌号、时间点、进/出;
2. 匹配同一车牌号的进出记录(按照时间先后),这就得先按照时间进行排序sort。然后从第一个 in 记录依次往后遍历,对于当前in记录(记为a)从它的后一个开始遍历整个车辆记录。如果遇到相同车牌号的in,就跳过这个a记录,意思是它在下一条in之前没有对应的out记录,所以要抛弃。如果遇到相同车牌号的out记录,就把这个匹配的记录存入到 Park结构体中,Park结构体:车牌号、进门时间left、出门时间right、存车时长time。遍历完之后就可以得到所有车辆的进出匹配记录。
3. 查询给定时间点校园内车辆个数,把这个时间点(记为time)转换为距离 00:00:00 的秒数,然后遍历所有 Park记录,如果time在这个park记录的左右边界之内,就说明这个时间点这辆车在校园内,注意,右边界不可取,对应记录 JH007BD 12:23:42 OUT 因为 这个时间点它都刚刚出门,还能算数吗,当然不能。
4.输出停车时间最长的车牌号,设置Time结构体,记录车牌号和对应的停车时长,遍历所有Park记录,存入。最后排序,输出第一个,并判断如果第二个时长和第一个相同,也输出。对应时间也要转换。这里我的这种做法有点繁琐了感觉,遍历太多次,如果在当初匹配进出记录时能不能就把车牌号对应的所有的进出记录同一存储,并存储总时长,那么是否方便了许多?
/**
* 02.23 08:46
*
**/
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
struct Record {
char id[10];
int h, m, s;
int status;
} rec[10010];
struct Park{ //存车结构体
char pid[10];
int left, right;// 记录左右边界
int time; // 存车时长
} p[10010];
struct Time{ //存车时长结构体
char id[10]; //车牌号
int time = 0; //存车时长
} t[10010];
int cntT = 0; //记录已经存了几个
bool cmp(Record a, Record b) {
if (a.h != b.h) {
return a.h < b.h;
} else if (a.m != b.m) {
return a.m < b.m;
} else {
return a.s < b.s;
}
}
bool cmpT(Time a, Time b){
if(a.time != b.time){
return a.time > b.time;
}else{
return strcmp(a.id, b.id) < 0;
}
}
int main() {
int n, k;
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i++) {
scanf("%s %d:%d:%d", rec[i].id, &rec[i].h, &rec[i].m, &rec[i].s);
char status[5];
scanf("%s", status);
if (strcmp(status, "in") == 0) {
rec[i].status = 1;
} else if (strcmp(status, "out") == 0) {
rec[i].status = 2;
}
}
//输入结束
printf("------------\n");
//---
sort(rec, rec + n, cmp);
/* for (int i = 0; i< n; i++){
printf("%s %02d:%02d:%02d time:%d\n", rec[i].id, rec[i].h, rec[i].m,
rec[i].s, rec[i].h * 3600 + rec[i].m * 60 + rec[i].s);
} */
// 存车记录 录入
int cnt = 0;
for (int i = 0; i < n; i++) {
char id[10];
if (rec[i].status == 1) { // 如果是in就往下找
strcpy(id, rec[i].id);
for (int j = i + 1; j < n; j++) {
if(strcmp(rec[j].id, id) == 0 && rec[j].status == 2){ //车牌号相同
strcpy(p[cnt].pid, id);
p[cnt].left = rec[i].h * 3600 + rec[i].m * 60 + rec[i].s; //左边界为距离00:00的秒数
p[cnt].right = rec[j].h * 3600 + rec[j].m * 60 + rec[j].s; //右边界边界为距离00:00的秒数
p[cnt].time = p[cnt].right - p[cnt].left; //记录存车时长
cnt++;
break; // 找到了就break
}else if(strcmp(rec[j].id, id) == 0 && rec[j].status == 1){ //如果下面出现了一个同样车牌号的in,就跳过当前循环
break; // 不应用continue,而应该用break也结束找out的循环
}
}
}
}
/*
// 输出存车记录
for (int i = 0; i < cnt; i++){
printf("%s %d %d\n", p[i].pid, p[i].left, p[i].right);
} */
// 开始查询
for (int i = 0; i < k; i++){
int h, m, s, seconds, cars = 0; // cars代表这个时间点校园内车的数量
scanf("%d:%d:%d", &h, &m, &s);
seconds = h * 3600 + m * 60 + s;
for (int j = 0; j < cnt; j++){
if(seconds >= p[j].left && seconds < p[j].right){
cars++;
}
}
printf("%d\n", cars);
}
// 开始遍历存车记录,将存车时长和车牌号对应起来
for (int i = 0; i < cnt; i++){
char idR[10];
strcpy(idR, p[i].pid); //存车记录中的车牌号
int j;
for (j = 0; j < cntT; j++){
if(strcmp(idR, t[j].id) == 0){ //如果在time结构体中找到和当前存车记录车牌号相同的数组
t[j].time += p[i].time;
}
}
if(j == cntT){ //没找到车牌号相同的
strcpy(t[cntT].id, idR);
t[cntT].time = p[i].time;
cntT++;
}
}
// 测试存车时长和车牌号对应起来
/* for (int q = 0; q < cntT; q++){
printf("%s %d\n", t[q].id, t[q].time);
} */
//排序,找到最大的存车时长
sort(t, t + cntT, cmpT);
printf("%s", t[0].id);
for (int i = 1; i < cntT; i++){
if(t[i].time == t[i-1].time){
printf(" %s", t[i].id);
}
else
break;
}
int h, m, s, time;
time = t[0].time;
h = time / 3600;
m = time % 3600 / 60;
s = time % 60;
printf(" %02d:%02d:%02d", h, m, s);
return 0;
}