[BaekJoon 13904 : Data Structure, Python] - 과제

2021, Dec 05    


백준 13904 과제 : 골드 3



Solution


import sys
input = sys.stdin.readline
from heapq import *
from collections import defaultdict

n = int(input())
tasks = []
howmany = defaultdict(int)
for _ in range(n):
    d, s = map(int, input().split())
    heappush(tasks, [-s, d])
    howmany[d] = 0              # 해당 마감일의 과제가 몇 번 count 됐는지 기록

cnt, max_d, total = 0, 0, 0
while tasks:
    cur_s, cur_d = heappop(tasks)
    if cnt >= cur_d:      # 현재까지 완료한 과제 수가 마감일보다 많을 때
        tmp_cnt = 0           
        for tmp_d in range(1, max_d + 1):       # 현재 마감일보다 마감일이 같거나 높은 모든 과제에 대해 양보 가능한지 확인
            tmp_cnt += howmany[tmp_d]
            if tmp_d >= cur_d and tmp_cnt >= tmp_d:      # 양보 불가
                break
        else:
            total += cur_s          # for-else 구문 : 현재 마감일 이전에 완료된 모든 과제가 양보 가능한 경우
            howmany[cur_d] += 1
            cnt += 1
    else:                       # 타겟 과제의 마감일이 완료한 과제수보다 클 때(아직 마감기한이 남은 경우), 그냥 넣어줌
        total += cur_s
        howmany[cur_d] += 1
        max_d = max(max_d, cur_d)
        cnt += 1

print(-total)


풀이과정 및 느낀점


  • 그리디 + 우선순위 큐를 사용해 문제를 풀었다.
  • 우선 점수가 높은 순대로 최대힙을 만든다
  • 그리디하게 점수 높은 과제 순서대로 total 점수에 합산하는데, 대신 아래의 조건을 따른다
    1. 현재까지 완료한 과제 수가 타겟 과제의 마감일보다 큰 경우
      • 타겟 과제보다 마감일이 같거나 높은 모든 과제가 양보가능한지 확인 (각 마감일까지 합산한 과제 수가 마감일보다 크거나 같으면 양보 불가)
    2. 타겟 과제의 마감일이 현재까지 완료된 과제수보다 크면 그냥 바로 total 점수에 합산함.

높은 점수 순대로 그리디하게 합산한다는 점까지는 알겠는데, 마감일까지 반영하는 조건을 생각해내는 게 까다로웠다. 다른 사람들 풀이를 보니 내 풀이보다 2배 이상 빠른 풀이가 있던데, 못 알아듣겠다.