본문 바로가기
백준

[백준] 19583번 : 싸이버개강총회 – JAVA [자바]

by Hongwoo 2023. 8. 1.
반응형

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

 

19583번: 싸이버개강총회

첫번째 줄에는 개강총회를 시작한 시간 S, 개강총회를 끝낸 시간 E, 개강총회 스트리밍을 끝낸 시간 Q가 주어진다. (00:00 ≤ S < E < Q ≤ 23:59) 각 시간은 HH:MM의 형식으로 주어진다. 두번째 줄부터는

www.acmicpc.net

 


  • 문제

 

 


  • 문제 풀이

백준 19583번 싸이버개강총회는 실버 2 난이도의 구현 및 해시 문제이다.

 

이 문제에서는 개강총회를 시작한 시간 S, 개강총회를 끝낸 시간 E, 개강총회 스트리밍을 끝낸 시간 Q가 주어진다. 그리고 채팅 기록들이 시간순으로 주어지는데 이때 출석이 확인된 학회원의 인원수를 출력하면 된다.

 

출석이 확인되는 조건은 다음과 같다. 

 

1. 개강총회를 시작하기 전에 채팅 기록이 있으면 제시간에 입장된 것으로 처리된다. 즉, 채팅 기록이 T 시간에 있었으면 T ≤ S여야지 제시간에 입장이 된 것이다.

2. 문제에는 다음과 같이 나와있다. "개강총회를 끝내고 나서, 스트리밍을 끝낼 때까지 학회원의 퇴장 확인 여부를 확인한다". 즉, 채팅 기록 시간이 T일 때, E ≤ T ≤ Q를 만족시켜야 한다.

 

즉, 따라서 출석이 확인되는 시간은 최소 두 개의 채팅 기록이 있어야 하고, 이 채팅 기록 시간을 T1, T2라고 했을 때, 다음 조건을 만족시켜야 한다.

1. T1 ≤ S

2. E ≤ T2 ≤ Q

 

이 문제에서는 시간이 HH:MM 형식으로 주어진다. 그리고, 이 시간들을 비교해야 하기 때문에 자바의 LocalTime 클래스를 이용하면 쉽게 풀 수 있다. 

 

LocalTime 클래스에 있는 함수들을 구체적으로 알고 싶다면 이 링크를 참고하면 되겠다.

 

이 문제에서는 LocalTime 객체 만드는 것과 시간 비교만 하면 되기 때문에 LocalTime.of(), isBefore(), isAfter() 함수만 알면 된다.

 

우선, HH:MM 형식인 문자열을 LocalTime 객체로 변환하기 위해 헬퍼 함수 timeMaker()를 만들었다. 

 

static LocalTime timeMaker(String s) {
    StringTokenizer st = new StringTokenizer(s, ":");
    LocalTime time = LocalTime.of(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
    return time;
}

 

이 함수는 문자열로 주어진 시간을 파싱 하여 LocalTime 객체로 변환하는 역할을 한다. 입력으로 주어지는 시간들은 HH:MM 형식으로 주어지는데, 이를 :를 기준으로 분리하여 LocalTime 객체로 변환하여 반환한다.

 

이제 매인 로직을 설명해 보겠다.

 

먼저, 개강총회 시작 시간(S), 끝난 시간(E), 스트리밍 끝난 시간(Q)을 입력받는다.

 

그리고 in이라는 세트를 만들어서 개강총회 시작 시간 이전에 대화한 학회원을 저장한다. 이 학회원들은 개강총회에 입장한 것으로 간주된다. 또한, counted라는 Set을 만들어서 이미 출석으로 확인된 학회원을 저장한다.

 

while-loop을 통해 채팅 기록들을 읽어오면서 다음과 같은 작업을 수행한다.


1. 각 채팅 기록에서 시간과 학회원 닉네임을 추출하여 time과 member 변수에 저장한다.
2. 개강총회 시작 전(time.isBefore(s) || time.equals(s))에 대화한 학회원은 입장한 것으로 간주하여 세트 in에 추가해 준다.

3. 개강총회 끝난 시간 이후, 스트리밍 끝난 시간 이전에 대화한 학회원 중 이미 입장한 학회원을 출석으로 간주하여 세트 counted에 추가해 준다.


최종적으로, counted는 출석이 확인된 인원들을 포함하고 있으므로 이 크기를 출력해 주면 된다.

 

자세한 코드는 아래에 있는 코드를 참고하면 되겠다.

 


  • 코드

 

import java.io.*;
import java.time.LocalTime;
import java.util.*;

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

        // 개강총회를 시작한 시간, 끝낸 시간, 스트리밍을 끝낸 시간을 입력 받음
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        String start = st.nextToken();
        String end = st.nextToken();
        String quit = st.nextToken();

        // 시간을 LocalTime 객체로 변환
        LocalTime s = timeMaker(start);
        LocalTime e = timeMaker(end);
        LocalTime q = timeMaker(quit);

        // 입장한 학회원을 저장할 Set 생성
        Set<String> in = new HashSet<>();

        // 이미 출석으로 확인된 학회원을 저장할 Set 생성
        Set<String> counted = new HashSet<>();

        String str;
        int count = 0;

        // 채팅 기록을 읽어오면서 출석 여부 확인
        while ((str = br.readLine()) != null) {
            st = new StringTokenizer(str, " ");
            LocalTime time = timeMaker(st.nextToken());
            String member = st.nextToken();

            // 개강총회 시작 전에 대화한 학회원은 입장으로 간주
            if (time.isBefore(s) || time.equals(s)) {
                in.add(member);
            }

            // 개강총회 끝난 시간 이후, 스트리밍 끝난 시간 이전에 대화한 학회원 중 이미 입장한 학회원을 출석으로 간주
            if ((time.isAfter(e) || time.equals(e)) && (time.isBefore(q) || time.equals(q))) {
                if (in.contains(member)) {
                    counted.add(member);
                }
            }
        }

        // 출석이 확인된 학회원의 인원 수 출력
        System.out.println(counted.size());
    }

    // 문자열을 LocalTime 객체로 변환하는 함수
    static LocalTime timeMaker(String s) {
        StringTokenizer st = new StringTokenizer(s, ":");
        LocalTime time = LocalTime.of(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
        return time;
    }
}

 

 

반응형

댓글