PAT-甲级-1095-Cars on Campus(30)

本篇博文代码使用Java,只通过以下样例
在这里插入图片描述

题目描述

Zhejiang University has 8 campuses and a lot of gates. From each gate
we can collect the in/out times and the plate numbers of the cars
crossing the gate. Now with all the information available, you are
supposed to tell, at any specific time point, the number of cars parking
on campus, and at the end of the day find the cars that have parked for
the longest time period.

输入格式:

Each input file contains one test case. Each case starts with two positive integers N (≤104), the number of records, and K (≤8×104) the number of queries. Then N lines follow, each gives a record in the format:

plate_number hh:mm:ss status

where plate_number is a string of 7 English capital letters or 1-digit numbers; hh:mm:ss represents the time point in a day by hour:minute:second, with the earliest time being 00:00:00 and the latest 23:59:59; and status is either in or out.

Note that all times will be within a single day. Each in record is paired with the chronologically next record for the same car provided it is an out record. Any in records that are not paired with an out record are ignored, as are out records not paired with an in record. It is guaranteed that at least one car is well paired in the input, and no car is both in and out at the same moment. Times are recorded using a 24-hour clock.

Then K lines of queries follow, each gives a time point in the format hh:mm:ss. Note: the queries are given in ascending order of the times.

输出格式:

For each query, output in a line the total number of cars parking on
campus. The last line of output is supposed to give the plate number of
the car that has parked for the longest time period, and the
corresponding time length. If such a car is not unique, then output all
of their plate numbers in a line in alphabetical order, separated by a
space.

输入样例:

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

输出样例:

1
4
5
2
1
0
1
JH007BD ZD00001 07:20:09

题目信息

作者: CHEN, Yue
单位: 浙江大学
时间限制: 300 ms
内存限制: 64 MB
代码长度限制: 16 KB

题目大意

浙江大学有很多车辆进出,我们从校门口收集到了车辆出入的时间和车牌号,如果给定某一时间,我们要输出当前时间校内有多少车,并在一天结束时输出停车时间最长的车辆

输入格式

每个输入文件包含一个测试用例。

第一行输入两个正整数:N(≤104)记录数据的数量,K(≤8×104)查询数。接下来是N行,每行给出一个格式的记录:

plate_number hh:mm:ss status

其中plate_number是由7个英文大写字母或1位数字组成的字符串;hh:mm:ss表示一天中的时间点,按小时:分:秒计算,最早时间为00:00:00,最晚时间为23:59:59
statusinout

注意:

  • 所有时间都在一天之内
  • 输入记录有很多是无法配对的,所以我们只将同一辆车的in和其在时间上临近的out匹配,忽略未配对的记录
  • 测试点的输入会保证至少一辆车的进入进出记录可以配对、且没有一辆车同时进出
  • 时间使用24小时制

之后输入K行查询信息,每行查询给出一个时间点,格式为hh:mm:ss。注:查询按时间升序排列。

输出格式

对于每个查询,输出一行当前查询输入的时间内校园内停车的总数。

最后一行输出应停车时间最长车辆的车牌号和相应的停车时长。

如果这样的车不是唯一的,那么将它们所有的车牌号按字母顺序排成一行,用空格隔开。

分析

既然要输出停车时间,那我们可以使用Map来存储每辆车的停车时间,最后输出的停车时长是需要比较的,那么将时长存储为秒更方便比较

车的有效匹配通过这样的排序获得:”将所有记录按照车牌号排序,如果车牌号相同就按照时间递增顺序排序“,排序之后判断当前记录与下一条记录的信息,将有效记录存起来

最后再将有效记录按照时间排序,对于到达查询时间之前的记录,in就将校内车辆总数+1out-1

输入样例说查询按照时间顺序输入的,所以我们可以利用这个进行优化,如果优化的话C++可能会有样例超时,而JAVA优化之前就已经超时到爷爷都不认识了,不过下面的JAVA代码我还是做了这里的优化

最后输出等待时间最长的车辆,如果有很多车,要按照车牌号的字典序输出,特别是JAVA选手,一定要注意这一点

代码步骤

  1. 将所有记录按照车牌号排序,如果车牌号相同就按照时间递增顺序排序
  2. 设置所有车辆最大停留allMaxTime时长为0
  3. 创建有效记录集合usefulRecords
  4. 对于排序之后的每条记录
    • 如果当前记录与下一条记录的车牌号相同当前记录为in,下一条记录为out,则说明这两条记录是有效的
      • 将这两条有效记录加入usefulRecords
      • 计算当前车辆停留时长waitTime
        • 如果当waitTime大于allMaxTimeallMaxTime = waitTime
        • 判断当前车牌号在Map中是否存在
          • 如果不存在,创建车牌号并存储waitTime
          • 如果存在,Map中当前车牌号的停留时间加上waitTime
  5. usefulRecords按照时间进行排序
  6. 对于每一个查询
    • usefulRecords的第一条记录开始,如果当前记录是in,则校内车辆数+1out-1
    • 如果要根据”查询是按照时间顺序输入的“来进行优化,可以在进行下一个查询之前记住当前是usefulRecord的第几个记录,因为usefulRecord我们按照时间排序了,下一个查询我们就可以从刚才记住的usefulRecord的时间开始,继续向后计算校内车辆数

常见问题

JAVA选手样例输出顺序不对

JAVA选手最后没有为车牌号排序的话,如果使用的MapHashMap,那么样例输出就会是ZD00001 JH007BD 07:20:09

对那些停留时间最长的那些车牌号按字典序排序再输出就好了

测试点3不能通过

  • 一种可能是JAVA选手使用TreeMap样例会正常输出,但是测试点3是过不去的,解决方法依旧是对那些停留时间最长的那些车牌号按字典序排序再输出

  • 另一种可能是把秒化成hh:MM:ss的格式时转化错误

    System.out.println(
        String.format("%02d",maxWaitTime/3600) + ":" +
        String.format("%02d",maxWaitTime%3600/60) + ":" +
        String.format("%02d",maxWaitTime%60)
    );
    

代码实现-JAVA

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


public class Main{
	public static void main(String[] args) throws IOException{
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		String[] tempStrArr = bf.readLine().split(" ");
		// 记录的数量
		int N = Integer.parseInt(tempStrArr[0]);
		//  查询的数量
		int K = Integer.parseInt(tempStrArr[1]);
		// 所有车停留时间
		Map<String, Integer> waitMap = new HashMap<String, Integer>();
		// 存放所有记录
		Record[] allRecord = new Record[N];
		// 存放有效的记录
		List<Record> usefulRec = new ArrayList<Record>();
        // 读取记录,存入allRecord
		for(int i=0; i<N; i++) {
			tempStrArr = bf.readLine().split(" ");
			Record newRecord = new Record(tempStrArr[0], tempStrArr[1], tempStrArr[2]);
			allRecord[i] = newRecord;
		}
        // 将所有记录按照 车牌号字典序 排序,如果车牌号相同就按照 时间递增顺序 排序
		Arrays.sort(allRecord, new NameAndTimeCom());
        
        // 设置 最大停留时间 为0
		int maxWaitTime = 0;
        
        // 数据从1开始读取,因为比较的是[i]和[i-1]
		for(int i=1; i<N; i++) {
            // [i]和[i+1]这两个临近的记录车牌相同,且是先in后out,则两条记录有效
			if((allRecord[i].cardID.equals(allRecord[i-1].cardID)) &&
					(allRecord[i].type.equals("out")) &&
					(allRecord[i-1].type.equals("in"))
				) {
                // 将 两条有效记录 加入 有效记录集合"usefulRec"
				usefulRec.add(allRecord[i-1]);
				usefulRec.add(allRecord[i]);
                // 计算 当前车牌的等待时间
				int waitTime = changeTimeToSecond(allRecord[i].time) - changeTimeToSecond(allRecord[i-1].time);
				if(waitTime > maxWaitTime) // 如果 当前等待时间 大于最 大停留时间
					maxWaitTime = waitTime; // 更新 最大停留时间
                // 如果 当前车牌 在 停留时间Map 中已存在
				if(waitMap.containsKey(allRecord[i].cardID)) { 
                    // 将这次的 停留时间 累积到 这个车牌号的停留时间 上
					waitMap.replace(allRecord[i].cardID, waitMap.get(allRecord[i].cardID)+waitTime);
				}else { // 如果 当前车牌 在 停留时间Map 中不存在
                    // 创建这个车牌号,存储停留时间
					waitMap.put(allRecord[i].cardID, waitTime);
				}
			}
		}
		
        // 对有效记录排序
		Collections.sort(usefulRec,new TimeCom());
        // 设置当前车数量为0
		int carsCount = 0;
        // 当前是 有效记录中 第几个记录
		int nowIndexInUsefulRec = 0;
		
        
		for(int i=0; i<K; i++) {
			String nowQueryTime = bf.readLine();
            // 读取 当前的有效记录,初始读取为第0个有效记录
			Record nowRecord = usefulRec.get(nowIndexInUsefulRec);
            
            
            // 如果 当前的车辆记录时间 在 查询时间 之前,或者刚好为查询时间,都进行校内总车辆的计算
			while(firstTimeIsEarlyOrSameTime(nowRecord.time, nowQueryTime) && (nowIndexInUsefulRec <= usefulRec.size())) {
				if(usefulRec.get(nowIndexInUsefulRec).type.equals("in")) //如果 当前有效记录 代表 车辆进入
					carsCount++; // 校内车辆+1
				else //如果 当前有效记录 代表 车辆驶出
					carsCount--; // 校内车辆-1
                // 前进到下一个有效记录
				nowIndexInUsefulRec++;
                // 获取下一个有效记录
				nowRecord = usefulRec.get(nowIndexInUsefulRec);
			}
            // 输出当前查询时间校内车数
			System.out.println(carsCount);
		}
		
        // 停留时间等于最大值的车牌号,用于最后进行字典序排序
		List<String> maxTimeCardID = new ArrayList();
		
        // 迭代 车辆停留时间Map,找到停留时间最长的一辆或几辆车,存入maxTimeCardID
		Iterator<Map.Entry<String, Integer>> iterator = waitMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> entry = iterator.next();
            if(entry.getValue() == maxWaitTime)
            	maxTimeCardID.add(entry.getKey() + " ");
        }
        
        
        // 对 停留时间等于最大值的车牌号 进行 字典序排序
        Collections.sort(maxTimeCardID, new NameCom());
        
        // 输出 停留时间等于最大值的车牌号
        for(int i=0; i<maxTimeCardID.size(); i++) {
        	System.out.print(maxTimeCardID.get(i));
        }
        
        // 最大停留时间转化成 hh:MM:ss 的格式
		System.out.println(
				String.format("%02d",maxWaitTime/3600) + ":" +
				String.format("%02d",maxWaitTime%3600/60) + ":" +
				String.format("%02d",maxWaitTime%60)
			);
	}
	
	
    // 将时间转化成秒
	public static int changeTimeToSecond(String time) {
		String[] tempArr = time.split(":");
		return Integer.parseInt(tempArr[0]) * 3600 + 
				Integer.parseInt(tempArr[1]) * 60 +
				Integer.parseInt(tempArr[2]);
	}
	
    // 判断 time1是否在time2之前 或者刚好等于time2
	public static boolean firstTimeIsEarlyOrSameTime(String time1, String time2) {
		return time1.compareTo(time2) <= 0;
	}

	
}

// 记录 类
class Record {
	String cardID;
	String time;
	String type;
	public Record(String cardID, String time, String type) {
		this.cardID = cardID;
		this.time = time;
		this.type = type;
	}
}

// 对记录按照 车牌号字典序 排序,如果车牌号相同就按照 时间递增顺序 排序
class NameAndTimeCom implements Comparator<Record>{
	@Override
	public int compare(Record o1, Record o2) {
		int s = o1.cardID.compareTo(o2.cardID);
		if(s == 0) {
			return o1.time.compareTo(o2.time);
		}else
			
			return s;
	}
}

// 对记录按照时间先后排序
class TimeCom implements Comparator<Record>{
	@Override
	public int compare(Record o1, Record o2) {
		return o1.time.compareTo(o2.time);
	}
}

//对字符串(本题用于对车牌号)按字典序排序
class NameCom implements Comparator<String>{
	@Override
	public int compare(String o1, String o2) {
		return o1.compareTo(o2);
	}
}
发布了52 篇原创文章 · 获赞 9 · 访问量 6243

猜你喜欢

转载自blog.csdn.net/weixin_43553694/article/details/104200314