[백준]부품 대여장 with Java

hyeok ryu·2024년 6월 11일
0

문제풀이

목록 보기
151/154

문제

https://www.acmicpc.net/problem/21942


입력

  • 첫 번째 줄에 부품 대여장에 작성된 정보의 개수 NN, 대여기간 LL, 벌금 FF이 공백으로 구분되어 주어진다.
  • 두 번째 줄부터 N+1N + 1번째 줄까지 시간순으로 부품 대여장에 작성한 정보 (시각, 부품 이름 PP, 회원 닉네임 MM)이 공백으로 구분되어 주어진다.

출력

  • 벌금을 내야하는 사람들을 사전순으로 동아리 회원 닉네임
    MM와 내야하는 벌금을 한 줄씩 출력한다.

만약 벌금을 내야하는 사람들이 없는 경우는 -1을 출력한다.


풀이

제한조건

접근방법

문자열 파싱, Map

문자열 파싱과 Map을 통해 해결할 수 있다.

단순 구현이지만, 어떤 점을 주의해야할지 먼저 생각해보자.

- 출력은 사전순으로 정렬되어야 한다.
- 한 사람이 동시에 여러개의 부품을 대여할 수 있다.
- 한 사람이 한 번만 등장하지 않는다. <- 매우 중요.

이제 벌금 계산 방식을 생각해보자.
특정 단위시간으로 변경 후, 시간의 차를 구하면 벌금의 유무를 확인할 수 있다.

어떻게 문제를 단순화 할 수 있을지 생각해보자.
대여자와 대여부품 시간을 따로 관리하는것은 번거롭다.

대여자가 동시에 여러 부품을 빌릴 수 있기 때문이다.

그럼 Map에 Key로 대여물품과 대여자를 함께 엮어서 사용하면 어떨까.
그럼 정말 단순해진다.

각 대여자와 물품이 하나의 Key로 묶이게 되므로, 대여시간을 value로 Map에 저장하면 모든 조건을 만족시키며 하나의 Map으로 관리할 수 있다.

벌금 계산시에는 Key값을 다시 Tokenize 하여 대여자를 특정할 수 있다..!

코드를 참고해보자.

Java에서 TimeFormatter를 이용하여 쉽게 분 단위의 시간 차이를 구할 수 있다.


코드

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class Main {
	static int fine;
	static long limitTime;
	static Map<String, Long> personFineMap = new TreeMap<>();
	static Map<String, String> personTimeMap = new HashMap<>();

	public static void main(String[] args) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader((System.in)));
		String[] inputs = in.readLine().split(" ");
		int T = stoi(inputs[0]);
		limitTime = getTimeLimit(inputs[1]);
		fine = stoi(inputs[2]);

		for (int tc = 0; tc < T; ++tc) {
			inputs = in.readLine().split(" ");
			String currentTime = inputs[0] + " " + inputs[1]; // YYYY-MM-DD hh:mm 구조
			String key = inputs[2] + inputs[3]; // 대여물품과 대여자를 하나로 묶어서 생각한다.
			if (personTimeMap.containsKey(key)) {
				// 빌린 기록이 있다면 대여시간을 충족하는지 확인해보자
				long total = getFine(personTimeMap.get(key), currentTime);
				if (total > 0) // 벌금이 존재한다.
					personFineMap.put(inputs[3], personFineMap.getOrDefault(inputs[3], 0L) + total);
				personTimeMap.remove(key); // 같은 대여자가 같은 물품을 다시 빌리는 경우가 있다. 기존 값을 지우자.

			} else {
				personTimeMap.put(key, currentTime); // 최초로 빌리는 경우다. 
			}
		}

		if (personFineMap.isEmpty()) {
			System.out.println(-1);
		} else {
			StringBuilder sb = new StringBuilder();
			for (String key : personFineMap.keySet())
				sb.append(key).append(" ").append(personFineMap.get(key)).append("\n");

			System.out.println(sb);
		}
	}

	private static long getFine(String startTime, String endTime) {
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
		LocalDateTime dt1 = LocalDateTime.parse(startTime, formatter);
		LocalDateTime dt2 = LocalDateTime.parse(endTime, formatter);

		Duration duration = Duration.between(dt1, dt2);
		long time = duration.getSeconds() / 60 - limitTime;
		if (time > 0)
			return time * fine;
		return 0;
	}

	private static long getTimeLimit(String s) {
		String[] tl = s.split("/");
		String[] hhmm = tl[1].split(":");
		return stoi(tl[0]) * 24 * 60 + stoi(hhmm[0]) * 60 + stoi(hhmm[1]);
	}

	private static int stoi(String s) {
		return Integer.parseInt(s);
	}
}

0개의 댓글