PAT甲组1095.Cars on Campus思路与注意点--补充《算法笔记》

A1095

题目链接

思路

此题由于时间限制,必须使用map映射才能通过测试点4,但思路与A1016基本一致,随后会更新map的方法
声明records结构体,按车牌号,时间先后顺序排序。随后标记其中的有效记录(in与out相邻),并在有效记录中统计数量(是有效记录并且满足时间这个条件),计算时间

注意点

1、一辆车多次进入时间停留,其在校园内的时间会累加
2、将时间转换为以秒为单位会方便比较

代码

#include <bits/stdc++.h>
using namespace std;
int N, K;
int maxAns;
int cars[5005];//以records的id为下标,记录某辆车总共停留的时间 
struct records{
	char num[15];
	int hh, mm, ss;
	int time;//以秒为单位方便比较询问的时间点 
	int maxTime;
	int id;//便于cars数组的散列进行累加 
	bool status;//true:in;false:out
	bool valid;//此条记录是否有效,true有效 
	records(){}
}rec[10005];
bool cmpTime(records r1, records r2)
{
	if(strcmp(r1.num, r2.num))
	{
		return strcmp(r1.num, r2.num) < 0;
	}
	else if(r1.hh != r2.hh)
	{
		return r1.hh < r2.hh;
	}
	else if(r1.mm != r2.mm)
	{
		return r1.mm < r2.mm;
	}
	else
	{
		return r1.ss < r2.ss;
	}
}
bool judge(int i, int t)//判断该车在这个时间点是否在校园内 
{
	records start = rec[i];
	records endd = rec[i + 1];
	if(start.time <= t && endd.time > t)
	{
		return true;
	}
	else
	{
		return false;
	}
}
int main(int argc, char *argv[]) {
	scanf("%d%d", &N, &K);
	for(int i = 0; i < N; i++)
	{
		char stat[5];
		scanf("%s %d:%d:%d %s", rec[i].num, &rec[i].hh, &rec[i].mm, &rec[i].ss, stat);
		if(!strcmp(stat, "in"))
		{
			rec[i].status = true;
		}
		if(!strcmp(stat, "out"))
		{
			rec[i].status = false;
		}
		rec[i].valid = false;//初始化全为false 
		rec[i].maxTime = 0;
		rec[i].time = rec[i].hh * 3600 + rec[i].mm * 60 + rec[i].ss;
	}
	sort(rec, rec + N, cmpTime);
	rec[0].id = 0;
	for(int i = 1; i < N; i++)
	{
		if(!strcmp(rec[i].num, rec[i - 1].num))
		{
			rec[i].id = rec[i - 1].id;
		}
		else
		{
			rec[i].id = i;
		}
	}
	//查找并标记有效记录 
	int in = 0, out = 0, next = 0, cnt = 0;
	while(in < N)
	{
		next = in;
		cnt = 0;
		while(next < N && !strcmp(rec[in].num, rec[next].num))//车牌相同
		{
			if(cnt == 0 && rec[next].status == true)//找到第一个in 
			{
				cnt = 1;
			}
			else if(cnt == 1 && rec[next].status == false)
			{
				cnt = 2;
			}
			next++;
		}
		if(cnt < 2)//说明没有有效记录 
		{
			in = next;
			continue; 
		}
		while(in < next)
		{
			while(in < next - 1 && !(rec[in].status == true && rec[in + 1].status == false)) 
			{
				in++;
			}
			rec[in].valid = true;
			out = in + 1;
			rec[out].valid = true;
			if(out == next)
			{
				in = next;
				break;
			}
			in = out + 1; 
		}
	}
	//K次询问输入 
	while(K--)
	{
		int cntCars = 0;
		int h, m, s, quesTime;
		scanf("%d:%d:%d", &h, &m, &s);
		quesTime = h * 3600 + m * 60 + s;
		for(int i = 0; i < N; i++)
		{
			if(rec[i].valid)//是有效的   这辆车in的位置 
			{
				if(rec[i].maxTime == 0 && rec[i].status)
				{
					cars[rec[i].id] += rec[i + 1].time - rec[i].time;
					rec[i].maxTime = rec[i + 1].time - rec[i].time;
					maxAns = max(maxAns, rec[i].maxTime);
				}
				if(judge(i, quesTime) && rec[i].status)
				{
					cntCars++;
					i++;
				}
			}
		}
		printf("%d\n", cntCars); 
	}
	for(int i = 0; i < N; i++)
	{
		if(cars[i] == maxAns)//此处有个小漏洞,下面会解释
		{
			printf("%s ", rec[i].num);
		}
	}
	printf("%02d:%02d:%02d\n", maxAns / 3600, maxAns % 3600 / 60, maxAns % 60);
	return 0;
}

其中发现了PAT这道题所有测试样例的一个漏洞,所有测试样例中没有全是累加获得的最长停留时间,总会有一个是连续时间内停车,然后做差得到的最大时间。

见代码最后一部分,maxAns是一次连续时间做差获得,而cars[]是进行累加的,如果所有车辆都是累加出来得到的最大时间(意思是,所有车辆一天至少进入了校园两次并且记录均有效),maxAns会小于cars[]中的所有数据,答案会出错。但PAT中并没有这样的测试样例,因此还有一丢丢漏洞。

使用map代码

#include <bits/stdc++.h>
using namespace std;
int N, K;
int maxAns = -1;
map<string, int> parkTime;
struct records{
	char num[15];
	int hh, mm, ss;
	int time;//以秒为单位方便比较询问的时间点 
	bool status;//true:in;false:out
	bool valid;//此条记录是否有效,true有效 
	records(){}
}rec[10005], validRec[10005];
bool cmpTime(records r1, records r2)//先按车牌排序,再按时间排序 
{
	if(strcmp(r1.num, r2.num))
	{
		return strcmp(r1.num, r2.num) < 0;
	}
	else if(r1.hh != r2.hh)
	{
		return r1.hh < r2.hh;
	}
	else if(r1.mm != r2.mm)
	{
		return r1.mm < r2.mm;
	}
	else
	{
		return r1.ss < r2.ss;
	}
}
bool cmpByTime(records r1, records r2)
{
	return r1.time < r2.time;
}
bool judge(int i, int t)//判断该车在这个时间点是否在校园内 
{
	records start = validRec[i];
	records endd = validRec[i + 1];
	if(start.time <= t && endd.time > t)//在校园内 
	{
		return true;
	}
	else//不在校园内 
	{
		return false;
	}
}
int main(int argc, char *argv[]) {
	scanf("%d%d", &N, &K);
	for(int i = 0; i < N; i++)//输入及初始化 
	{
		char stat[5];
		scanf("%s %d:%d:%d %s", rec[i].num, &rec[i].hh, &rec[i].mm, &rec[i].ss, stat);
		if(!strcmp(stat, "in"))
		{
			rec[i].status = true;
		}
		if(!strcmp(stat, "out"))
		{
			rec[i].status = false;
		}
		parkTime[rec[i].num] = 0; 
		rec[i].valid = false;//初始化全为false 
		rec[i].time = rec[i].hh * 3600 + rec[i].mm * 60 + rec[i].ss;
	}
	sort(rec, rec + N, cmpTime);
	int index = 0;
	for(int i = 0; i < N - 1; i++)
	{
		if(!strcmp(rec[i].num, rec[i + 1].num) && rec[i].status && !rec[i + 1].status)
		{
			validRec[index++] = rec[i];
			validRec[index++] = rec[i + 1];
			int inTime =  rec[i + 1].time - rec[i].time;
			parkTime[rec[i].num] += inTime;
			maxAns = max(maxAns, parkTime[rec[i].num]);
		}
	}
	//K次询问输入 
	sort(validRec, validRec + index, cmpByTime);
	int now = 0, cntCars = 0;
	bool isfir = false;
	while(K--)
	{
		int h, m, s, quesTime;
		scanf("%d:%d:%d", &h, &m, &s);
		quesTime = h * 3600 + m * 60 + s;
		while(now < index && validRec[now].time <= quesTime)
		{
			if(validRec[now].status)
			{
				cntCars++;
			}
			else
			{
				cntCars--;
			}
			now++;
		}
		printf("%d\n", cntCars); 
		isfir = true;
	}
	for(map<string, int>::iterator it = parkTime.begin(); it != parkTime.end(); it++)
	{
		if(it->second == maxAns)
		{
			printf("%s ", it->first.c_str()); 
		}
	}
	printf("%02d:%02d:%02d\n", maxAns / 3600, maxAns % 3600 / 60, maxAns % 60);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值