1. 문제

19583번: 싸이버개강총회



2. 개요

회전초밥 가게에서 두가지 이벤트를 동시에 진행한다.

  1. 원래 회전 초밥은 손님이 마음대로 초밥을 고르고, 먹은 초밥만큼 식대를 계산하지만, 벨트의 임의의 한 위치부터 k개의 접시를 연속해서 먹을 경우 할인된 정액 가격으로 제공한다.
  2. 각 고객에게 초밥의 종류 하나가 쓰인 쿠폰을 발행하고, 1번 행사에 참가할 경우 이 쿠폰에 적혀진 종류의 초밥 하나를 추가로 무료로 제공한다. 만약 이 번호에 적혀진 초밥이 현재 벨트 위에 없을 경우, 요리사가 새로 만들어 손님에게 제공한다.

회전벨트의 상태, 초밥의 가짓수, 연속으로 먹을 접시의 개수, 쿠폰으로 받은 초밥의 종류가 각각 주어졌을 때, 손님이 먹을 수 있는 초밥의 최대 종류를 구하는 문제.



3. 풀이 및 코드

3-1. 풀이

싸이버개강총회를 진행하려고 한다. 이 총회의 출석은 다음과 같은 방식을 통해 확인하려고 한다.

  1. 개강총회를 시작하기 전에, 학회원의 입장 확인 여부를 확인한다. 학회원의 입장 여부는 개강총회가 시작한 시간 이전에 대화를 한 적이 있는 학회원의 닉네임을 보고 체크한다. 개강총회를 시작하자마자 채팅 기록을 남긴 학회원도 제 시간에 입장이 확인된 것으로 간주한다.
  2. 개강총회를 끝내고 나서, 스트리밍을 끝낼 때까지 학회원의 퇴장 확인 여부를 확인한다. 학회원의 퇴장 여부는 개강총회가 끝나고 스트리밍이 끝날 때까지 대화를 한 적이 있는 학회원의 닉네임을 보고 체크한다. 개강총회가 끝나자마자 채팅 기록을 남겼거나, 개강총회 스트리밍이 끝나자마자 채팅 기록을 남긴 학회원도 제 시간에 퇴장이 확인된 것으로 간주한다.

이 때, 출석이 확인된 인원수를 구하는 문제.

주어지는 시간이 모두 같은 날의 00:00 ~ 24:00 이므로 이를 정수화하여 사용할 수 있다.

만약 총회 시작 전의 기록이라면 입장확인 집합에 기록하고, 총회 종료 ~ 스트리밍 종료 사이의 기록이라면 퇴장확인 집합에 기록한다.

입장확인 기록과 퇴장확인 기록의 교집합이 온전한 출석체크 기록이 되므로 이 교집합의 크기를 출력한다.

3-2. Python

import sys

S, E, Q = sys.stdin.readline().split()

S = ''.join(S.split(':'))
E = ''.join(E.split(':'))
Q = ''.join(Q.split(':'))

S, E, Q = int(S), int(E), int(Q)

enterchk = set()
exitchk = set()

while True:
    info = list(sys.stdin.readline().split())
    if not info:
        break

    infotime = ''.join(info[0].split(':'))
    infotime = int(infotime)

    if infotime <= S:
        enterchk.add(info[1])

    elif E <= infotime <= Q:
        exitchk.add(info[1])

chked = enterchk.intersection(exitchk)
print(len(chked))

3-3. C#

namespace boj_19583
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string[] input = Console.ReadLine().Split();

            int S = int.Parse(string.Join("", input[0].Split(":")));
            int E = int.Parse(string.Join("", input[1].Split(":")));
            int Q = int.Parse(string.Join("", input[2].Split(":")));

            HashSet<string> enterChk = new();
            HashSet<string> exitChk = new();

            while (true)
            {
                string info = Console.ReadLine();

                if (info == "" || info == null)
                    break;

                string[] infos = info.Split();

                int infoTime = int.Parse(string.Join("", infos[0].Split(":")));

                if (infoTime <= S)
                    enterChk.Add(infos[1]);

                else if (infoTime >= E && infoTime <= Q)
                    exitChk.Add(infos[1]);
            }

            List<string> intersection = enterChk.Intersect(exitChk).ToList();
            Console.WriteLine(intersection.Count);
        }
    }
}

Comments