문제 링크

문제 요약

아르투라스는 대학교 첫 학기에 10개의 과목을 선택했습니다.

그는 선택한 과목들의 강의 시간이 겹치는지 확인하고 싶어 합니다. 강의 시간이 겹친다는 것은 두 과목의 강의 시간이 동시에 진행되는 경우를 의미하며, 한 강의가 끝나는 동시에 다른 강의가 시작하는 경우는 겹치지 않는 것으로 간주합니다.

입력은 10개의 강의 정보로 구성되며, 각 강의는 요일(1-5), 시작 시간(시, 분), 종료 시간(시, 분)으로 주어집니다.

모든 강의를 수강할 수 있다면 “TAIP”와 총 강의 시간을 시, 분 형식으로 출력합니다. 만약 강의가 겹치는 경우가 있다면 “NE”와 겹치는 두 강의의 1부터 10까지의 번호를 출력합니다. (여러 쌍이 겹칠 경우, 아무 한 쌍만 출력하면 됩니다.)

풀이

이 문제는 주어진 10개의 강의 시간표에서 시간 중복 여부를 판별하는 문제입니다. 강의 개수가 10개로 매우 적으므로, 모든 강의 쌍을 비교하여 겹치는 부분이 있는지 확인하는 방식으로 접근할 수 있습니다.

  1. 시간 변환: 강의 시간(hh:mm)을 분 단위로 통일하여 비교를 용이하게 합니다. hh * 60 + mm 분으로 변환하여 자정부터의 총 분으로 표현합니다. 이는 to_number 함수로 구현되었습니다.

  2. 중복 판별 함수 (is_intersection):

    • 두 강의가 같은 요일(s 값)에 진행되는지 먼저 확인합니다. 다른 요일이라면 절대 겹칠 수 없습니다.
    • 같은 요일이라면, 두 강의의 시작 시간과 종료 시간을 분 단위로 변환하여 두 개의 시간 구간 [시작_1, 종료_1)[시작_2, 종료_2)를 얻습니다. 여기서 종료 시간은 포함하지 않는 반개구간으로 생각하는 것이 편리합니다.
    • 문제에서 “한 강의가 끝나는 동시에 다른 강의가 시작하는 경우는 겹치지 않는 것으로 간주”한다고 명시했으므로, 두 구간 [a_start, a_end)[b_start, b_end)가 있을 때, a_end == b_start 또는 b_end == a_start인 경우는 겹치지 않아야 합니다.
    • 제공된 코드의 is_intersection 함수는 두 시간 구간을 정렬한 후, 첫 번째 구간의 종료 시간이 두 번째 구간의 시작 시간보다 작거나 같으면 겹치지 않는 것으로 판단합니다 (class_time[0][1] <= class_time[1][0]). 이 조건이 True이면 겹치지 않고, False이면 겹치는 것입니다. 이 로직은 max(start1, start2) < min(end1, end2)와 같은 효과를 가집니다. 즉, 두 구간 [min_start, min_end)[max_start, max_end)이 있을 때, min_end > max_start인 경우에만 겹친다고 판단하며, 이는 문제의 요구사항(끝나는 시점에 바로 다음 강의가 시작하는 경우 겹치지 않음)을 정확히 만족합니다.
  3. 모든 쌍 비교: 10개의 강의가 있으므로, 중첩 반복문을 사용하여 모든 가능한 두 강의 쌍(총 10 * 9 / 2 = 45 쌍)에 대해 is_intersection 함수를 호출합니다.

    • for i in range(10):
    • for j in range(i + 1, 10):
    • 만약 한 쌍이라도 겹치는 것을 발견하면, 즉시 “NE”와 해당 강의들의 1-기반 인덱스(i+1, j+1)를 출력하고 프로그램을 종료합니다.
  4. 총 강의 시간 계산: 모든 쌍을 확인한 후에도 겹치는 강의가 없다면, “TAIP”를 출력하고 모든 강의의 총 시간을 합산합니다. 각 강의의 총 시간은 (종료 시간 - 시작 시간)을 분 단위로 계산한 후, 모든 강의의 분을 더합니다. 최종적으로 이 총 분을 시와 분으로 변환하여 출력합니다.

정답 코드

def to_number(h, m):
  return h * 60 + m
 
def is_intersection(a, b):
  # 요일이 다르면 겹치지 않음
  if a[0] != b[0]:
    return False
  
  # 강의 시작/종료 시간을 분 단위로 변환
  class_time = [
    (to_number(a[1], a[2]), to_number(a[3], a[4])),
    (to_number(b[1], b[2]), to_number(b[3], b[4]))
  ]
  
  # 시간 구간을 시작 시간을 기준으로 정렬
  class_time.sort()
 
  # 겹치지 않는 조건: 첫 번째 강의가 끝나는 시간 <= 두 번째 강의가 시작하는 시간
  # (문제 조건: 한 강의가 끝나는 동시에 다른 강의가 시작하는 경우는 겹치지 않음)
  if class_time[0][1] <= class_time[1][0]:
    return False
  
  # 위 조건에 해당하지 않으면 겹치는 것임
  return True
 
def solve():
  time_table = [[*map(int, input().split())] for _ in range(10)] # 10개의 강의 정보 입력
 
  # 모든 강의 쌍에 대해 중복 여부 확인
  for i in range(10):
    for j in range(i + 1, 10): # 중복 및 자기 자신 제외
      if is_intersection(time_table[i], time_table[j]):
        print("NE") # 겹치는 경우 "NE" 출력
        print(i + 1, j + 1) # 1-기반 인덱스로 강의 번호 출력
        return # 바로 종료
 
  # 겹치는 경우가 없는 경우
  print("TAIP") # "TAIP" 출력
 
  ans = 0
  # 모든 강의의 총 시간 계산
  for i in range(10):
    ans += to_number(time_table[i][3], time_table[i][4]) - to_number(time_table[i][1], time_table[i][2])
  
  # 총 시간을 시, 분으로 변환하여 출력
  print(ans // 60, ans % 60)
 
 
if __name__ == "__main__":
  tc = 1
  for t in range(1, tc+1):
    ret = solve()
 

연관 페이지

참고 문헌 / 사이트