[BOJ] 21942번 부품 대여장 - JAVA

최영환·2024년 8월 6일
0
post-thumbnail

💡 문제

💬 입출력 예시

📌 풀이(소스코드)

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.TreeMap;

public class Main {

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String[] input = br.readLine().split(" ");
        int N = Integer.parseInt(input[0]);
        int F = Integer.parseInt(input[2]);

        // 시간 파싱
        String[] date = input[1].split("/");
        String[] time = date[1].split(":");
        int limitDay = Integer.parseInt(date[0]);
        int limitHour = Integer.parseInt(time[0]);
        int limitMinute = Integer.parseInt(time[1]);
        long limitTime = limitDay * 24L * 60L + limitHour * 60L + limitMinute;  // 분으로 환산된 대여기간

        // Key 가 회원, 부품이고 value 가 일자 및 시간인 HashMap
        // Key 가 회원이고 value 가 벌금인 TreeMap
        HashMap<String, String> rentalMap = new HashMap<>();
        TreeMap<String, Long> fineMap = new TreeMap<>();
        for (int i = 0; i < N; i++) {
            input = br.readLine().split(" ");

            String value = input[0] + " " + input[1];
            String key = input[2] + input[3];

            if (rentalMap.containsKey(key)) {
                // 이미 있는 경우의 처리
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
                LocalDateTime startTime = LocalDateTime.parse(rentalMap.get(key), formatter);
                LocalDateTime endTime = LocalDateTime.parse(value, formatter);

                Duration duration = Duration.between(startTime, endTime);

                long delayTime = duration.getSeconds() / 60 - limitTime;
                if (delayTime > 0) {
                    long totalFine = delayTime * F;
                    if (totalFine > 0) {
                        fineMap.put(input[3], fineMap.getOrDefault(input[3], 0L) + totalFine);
                    }
                }

                rentalMap.remove(key);    // 같은 물건은 중복해서 대여할 수 없으므로 맵에서 제거
            } else {
                rentalMap.put(key, value);  // 중복이 없으므로 맵에 바로 등록
            }
        }

        // 벌금 낼 사람이 없으므로 -1 출력
        if (fineMap.isEmpty()) {
            System.out.println(-1);
            return;
        }

        // 벌금을 내야하는 사람과 요금 출력
        StringBuilder sb = new StringBuilder();
        for (String key : fineMap.keySet()) {
            sb.append(key).append(" ").append(fineMap.get(key)).append("\n");
        }
        System.out.println(sb);
    }

}

📄 해설

접근

  • 시간 관련 라이브러리를 잘 활용해야하는 문제. 작성자는 해당 라이브러리를 많이 사용해보질 않아, 다른 풀이를 확인하고 풀었다. 나중에 다시 풀어봐야할 문제다.
  • 대여장을 표현하기 위해 Key 가 회원, 부품이고 Value 가 일자 및 시간인 HashMap 을 사용하고, 이름순으로 정렬된 벌금 장부를 표현하기 위해 Key 가 회원이고 Value 가 벌금인 TreeMap 을 사용한다.
  • 대여장에 이미 대여 내역이 있는 경우 벌금을 계산하고 대여장에서 해당 내역을 제거하고, 없는 경우 그냥 대여장에 추가한다.

과정

  • 입력 받은 문자열을 파싱해서 대여 기간을 구한다.
  • 이후 N개의 입력을 받으면서, 입력 받은 문자열을 파싱해서 대여장을 표현하는 rentalMap 에 파싱해서 만든 Key 가 이미 존재하는 경우와 그렇지 않은 경우로 처리가 나뉜다.
  • 이미 대여장에 현재 입력받은 회원과 부품이 Key로 존재하는 경우, rentalMap 에 저장된 일자 및 시간과 현재 입력 받은 일자 및 시간과의 차이를 계산하고, 연체한 경우 벌금을 계산해서 fineMap 에 벌금을 추가한다. 그 다음 같은 물건은 중복 대여가 불가능 하므로, rentalMap 에서 해당 회원과 부품을 제거한다.
  • 대여장에 현재 입력 받은 회원과 부품이 존재하지 않는 경우, 단순히 rentalMap 에 추가한다.
  • 벌금을 저장하고 있는 fineMap 이 비어있지 않은 경우 -1을 출력하고, 그렇지 않으면 fineMap 에 존재하는 모든 회원의 벌금을 함께 출력한다. 이때, TreeMap 이므로 이미 이름 순으로 정렬이 되어있다.
profile
조금 느릴게요~

0개의 댓글