PAT A1095 Cars on Campus

本文详细解析了PATA1095停车场管理问题的算法解决方案,包括数据预处理、车辆进出记录分析、最大停留时间计算及查询时刻在校车辆数的统计。通过双指针法和打表法优化查询效率,实现对海量数据的有效管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PAT A1095 Cars on Campus

在这里插入图片描述在这里插入图片描述

Sample Input:

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

Sample Output:

1
4
5
2
1
0
1
JH007BD ZD00001 07:20:09
  • PAT A1016 Phone Bills (25分) 改版

  • 思路 1:
    先按车牌排序(同车牌按时间先后排序),排序后从头到尾遍历,筛选出有效数据(同一辆车:前一记录in,后out) valid[ ],筛选的过程中,将同一辆车停留时长累加到map中,使车牌和时长对应
    再将valid[ ]按时间先后排序
    对每一输入查询时刻,从头开始遍历,找出这一时刻前的所有记录,对in计数器cnt++,out计数器cnt–;
    再通过对map的遍历,得到当天最大停留时长,即对应的车s

  • code 1:

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string>
#include <map>
using namespace std;
int n, k;
map<string, int> mp;	//存储每辆车对应的停留时间 -> 求最大停留时间 
struct Car{
	string pNum;
	int h, m, s, time;	//time:进/出发生的时刻(以s为单位)  
	bool flag;	//true=in false=out
}cars[10010], valid[10010];
bool cmp1(Car a, Car b){
	if(a.pNum != b.pNum) return a.pNum < b.pNum;
	else return a.time < b.time;
}
bool cmp2(Car a, Car b){
	return a.time < b.time;
}
int tTos(int h, int m, int s){
//把格式化时间hh:mm:ss 转化为以s为单位的整数 
	int t = h * 3600 + m * 60 + s;
	return t;	
}
void sTot(int s){
//格式化输出 
	int h = s/3600;
	int m = s%3600/60;
	int ss = s - h*3600 - m*60;
	printf("%02d:%02d:%02d", h, m, ss);
}

int main(){
	scanf("%d %d", &n, &k);
	string f;
	for(int i = 0; i < n; ++i){
		cin >> cars[i].pNum;
		scanf("%d:%d:%d", &cars[i].h, &cars[i].m, &cars[i].s);
		cin >> f;
		if(f == "in") cars[i].flag = true;
		else cars[i].flag = false;
		cars[i].time = tTos(cars[i].h, cars[i].m, cars[i].s);
	}	
	sort(cars, cars+n, cmp1);
	//1.筛选出有效数据
	int idex = 0;
	for(int i = 1; i < n; ++i){
		if(cars[i].pNum == cars[i-1].pNum){
			if(cars[i].flag == false && cars[i-1].flag == true){
				valid[idex] = cars[i-1];
				valid[++idex] = cars[i];
				mp[cars[i].pNum] += cars[i].time - cars[i-1].time;
				idex++;
			} 
		}
	} 
	sort(valid, valid+idex, cmp2);
	//查找输入时刻还在学校的车数:遍历输入时刻之前的所有记录 in:cnt++ | out:cnt--; 
	int cnt, qH, qM, qS; 
	for(int i = 0; i < k; ++i){
		scanf("%d:%d:%d", &qH, &qM, &qS);
		int tt = tTos(qH, qM, qS);
		cnt = 0;
		for(int j = 0; j < idex; ++j){
			if(valid[j].time <= tt){
				if(valid[j].flag == true) cnt++;
				else cnt--;
			}else break;
		}
		printf("%d\n", cnt);
	}
	//先遍历一遍map找最大值,再遍历一次把和最大值相等的车牌输出 
	int Max = 0;
	for(auto it = mp.begin(); it != mp.end(); ++it){
		if(it->second > Max){
			Max = it->second;
		}
	}
	for(auto it = mp.begin(); it != mp.end(); ++it){
		if(it->second == Max){
			cout << it->first << " ";
		}
	}
	sTot(Max);
	return 0;
} 
  • 思路 2:
    求最大值操作可以放到,处理原始数据的循环里(即筛选有效数据的循环),在筛选的过程中不断更新Max

  • code 2: 部分

int inTime = cars[i].time - cars[i-1].time;
if(mp.count(cars[i].pNum) == 0){
	mp[cars[i].pNum] = 0;	//map中没有这个车牌 置0 
}
mp[cars[i].pNum] += inTime;	//累加该车总停留时长
maxTime = max(maxTime, mp[cars[i].pNum]);	//更新全局maxTime
  • 思路2:双指针法+打表法
    对有效数据的处理,类似于 Phone Bills ,用双指针分组遍历
    对查询部分,采用预处理,求出每一秒的状态(从0遍历到243600+6060+60 = 90060,q[i] += q[i-1])存到q[]中,直接将查询时间hh:mm:ss转换成秒t,输出q[t]即可

  • T2 code :

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int q[maxn];	//打表:用于记录,每一秒学校内的车数 
struct Record{
	string plate;
	int h, m, s, time, status;
}re[maxn];
struct Car{
	string plate;
	int park;
}car[maxn];
bool cmp(Record a, Record b){
	return a.plate != b.plate ? a.plate < b.plate : a.time < b.time; 
}
int main(){
	int nr, nq;
	scanf("%d %d", &nr, &nq);
	for(int i = 0; i < nr; ++i){
		cin >> re[i].plate; 
		scanf("%d:%d:%d", &re[i].h, &re[i].m,& re[i].s);
		string ss; cin >> ss; if(ss[0] == 'o') re[i].status = 1;	//0 == in , 1 == out 
		re[i].time = re[i].h * 3600 + re[i].m * 60 + re[i].s;
	}
	sort(re, re+nr, cmp);
	int i = 0, j = 1, idex = 0, max_time = 0;
	memset(q, 0, sizeof(q));
	while(j < nr){
		while(re[j].plate == re[i].plate) j++;
		int k = i;
		while(k + 1 < j){
			if(re[k].status == 0 && re[k+1].status == 1){
				car[idex].plate = re[i].plate;
				int in_time = re[k].time, out_time = re[k+1].time;
				int d = out_time - in_time;
				q[in_time]++; q[out_time]--;
				car[idex].park += d;
				max_time = max(max_time, car[idex].park);	//找出最大停留时长 
				k += 2;
			}else k++;
		}
		idex++;
		i = j++;
	}
	//求出每一秒学校内的车数:打表 
	for(int i = 1; i < maxn; ++i){
		q[i] += q[i-1];
	}
	for(int i = 0; i < nq; ++i){
		int qh, qm, qs;
		scanf("%d:%d:%d", &qh, &qm, &qs);
		int qt = qh * 3600 + qm * 60 + qs;
		printf("%d\n", q[qt]);
	}
	for(int i = 0; i < idex; ++i){
		if(car[i].park == max_time) cout << car[i].plate << " ";
	}
	printf("%02d:%02d:%02d", max_time / 3600, max_time / 60 % 60, max_time % 60);
	return 0;
}
  • T3 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010;
int time_table[100010], max_parktime = 0;
map<string, int> park_time;
struct Record
{
    string plate;
    int time, status;
}record[maxn];

int GetTime(int h, int m, int s) { return h * 3600 + m * 60 + s; }
bool cmp(Record a, Record b) { return a.plate != b.plate ? a.plate < b.plate : a.time < b.time; }

void DealRecord(int n)
{
    int left = 0, right = 1;
    while(left < n)
    {
        while(right < n && record[right].plate == record[left].plate) right++;
        for(int i = left+1; i < right; ++i)
        {
            if(record[i].status == -1 && record[i-1].status == 1)
            {
                int in = record[i-1].time, out = record[i].time;
                park_time[record[i].plate] += (out - in);
                time_table[in]++; time_table[out]--;
                max_parktime = max(park_time[record[i].plate], max_parktime);
            }
        }
        left = right++;
    }
}

int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; ++i)
    {
        int th, tm, ts;
        string tsign;
        cin >> record[i].plate;
        scanf("%d:%d:%d", &th, &tm, &ts);
        cin >> tsign;
        record[i].time = GetTime(th, tm, ts);
        record[i].status = tsign[0] == 'i' ? 1 : -1;
    }
    sort(record, record + n, cmp);
    DealRecord(n);
    int last_time = -1, last_num = 0;   //WRONG:样例 1, 5 :注意:last_time要从-1开始,因为有可能查询00:00:00
    for(int i = 0; i < m; ++i)
    {
        int qh, qm, qs;
        scanf("%d:%d:%d", &qh, &qm, &qs);
        int qt = GetTime(qh, qm, qs);
        for(int j = last_time+1; j <= qt; ++j)
        {
            if(time_table[j] != 0) last_num += time_table[j];
        }
        printf("%d\n", last_num);
        last_time = qt;
    }
    for(auto it = park_time.begin(); it != park_time.end(); ++it)
    {
        if(it->second == max_parktime) cout << it->first << " ";
    }
    printf("%02d:%02d:%02d", max_parktime / 3600, max_parktime / 60 % 60, max_parktime % 60);
    return 0;
}
  • T4 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 24 * 60 * 60;
int status[maxn];
struct record
{
    int _time;
    bool _sign;  // 1 in , 0 out;
};
unordered_map<string, vector<record> > mp;
bool cmp(record & a, record & b)
{
    if(a._time != b._time)
    {
        return a._time < b._time;
    }else
    {
        return a._sign > b._sign;
    }
}
int GetTime(int h, int m, int s)
{
    return h * 60 * 60 + m * 60 + s;
}
void PrintTime(int t)
{
    printf("%02d:%02d:%02d", t / 60 / 60 , t / 60 % 60 , t % 60);
}

int Max = 0;
set<string> winner;
void GetLongest(string plate, vector<record> & ans)
{
    int sum = 0;
    for(int i = 1; i < ans.size(); ++i)
    {
        if(ans[i]._sign == false && ans[i-1]._sign == true)
        {
            int in = ans[i-1]._time, out = ans[i]._time;
            status[in]++;
            status[out]--;
            sum += out - in;
        }
    }
    if(sum > Max)
    {
        Max = sum;
        winner.clear();
        winner.insert(plate);
    }else if(sum == Max)
    {
        winner.insert(plate);
    }
}
int main()
{
    int n, nq;
    scanf("%d %d", &n, &nq);
    for(int i = 0; i < n; ++i)
    {
        string tplate, tsign;
        int th[3];
        cin >> tplate;
        scanf("%d:%d:%d", &th[0], &th[1], &th[2]);
        cin >> tsign;
        int ttime = GetTime(th[0], th[1], th[2]);
        mp[tplate].push_back(record{ttime, tsign[0] == 'i' ? true : false});
    }
    for(auto it = mp.begin(); it != mp.end(); ++it)
    {
        sort(it->second.begin(), it->second.end(), cmp);
        GetLongest(it->first, it->second);
    }
    int num = 0, pre = 0, now;
    for(int i = 0; i < nq; ++i)
    {
        int th, tm, ts;
        scanf("%d:%d:%d", &th, &tm, &ts);
        now = GetTime(th, tm, ts);
        for(int j = pre; j <= now; ++j)
        {
            if(status[j])
            {
                num += status[j];
            }
        }
        printf("%d\n", num);
        pre = now+1;
    }
    for(auto it : winner) cout << it << " ";
    PrintTime(Max);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值