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);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章