자료구조&알고리즘/알고리즘 - 대회 알고리즘

[알고리즘 문제 풀이][탐욕] 백준 2109번 - 순회강연

초코쨔응 2021. 12. 6. 22:54

백준 2109번 순회강연 문제입니다.

(탐욕 알고리즘 or 우선순위 큐)

 

- 문제 설명: https://www.acmicpc.net/problem/2109

- 문제 풀이:

 

본 문제는 탐욕 알고리즘 혹은 우선순위 큐로 풀이 가능합니다. (시간이 2초이고, 입력 크기가 10,000 이므로 N^2 알고리즘 가능)

 

탐욕 알고리즘을 쓰는 경우에는 pay 가 큰 값부터 작은 값으로 정렬해주고 (d일 이내에 와야한다는 조건 때문에 오름차순이 아닌 내림차순으로 풀이하게 됩니다), pay 가 큰 값부터 우선적으로 day 에 지정해줍니다. 그런데, day 값을 그 기간 안에 오기만 하면 되는 것이기 때문에 1일차부터 주어진 day 까지 다 확인하면서 지정해줍니다.

(자세한 설명: https://steady-coding.tistory.com/231)

 

우선순위 큐를 쓰는 경우에는 강연이 가능한 가장 마지막 날부터 강연을 요청한 곳들의 pay 를 우선순위 큐에 넣습니다. 그 중 가장 pay를 크게 주는 값을 pop 합니다. 그리고 그 전 날짜로 가면서 우선순위 큐에 그 전 날짜들의 pay 를 추가합니다. 이들 중에 또 가장 pay 를 크게 주는 값을 pop 합니다. 이런식으로 1 일차까지 정해지도록 하면 됩니다.

(자세한 설명: https://velog.io/@ha-mulan/%EB%B0%B1%EC%A4%80-2109%EB%B2%88-%EC%88%9C%ED%9A%8C%EA%B0%95%EC%97%B0)

 

- 코드

탐욕 알고리즘

visited = [0]*10001

N = int(input())
pos = []
for i in range(N):
    pos.append(list(map(int, input().split())))

ans = 0

if len(pos):
    pos.sort(key = lambda x: -x[0])
    for i in range(N):
        for j in range(pos[i][1], 0, -1): # 1 일차까지만
            if visited[j] == 0:
                ans += pos[i][0]
                visited[j] = 1
                break

print(ans)

 

우선순위 큐

(출처: https://www.acmicpc.net/source/18112650)

from heapq import *

n = int(input())
tasks = [[] for i in range(10001)]
for i in range(n):
    p, d = map(int,input().split())
    tasks[d].append(p)
heap = []
ans = 0
for i in range(10000, 0, -1):
    for x in tasks[i]: heappush(heap, -x)
    if heap: ans+= -heappop(heap)
print(ans)

 

 

- 실수 포인트 & 반례:

1. 인덱스 에러

코드에서 10000 일이 들어올 수 있는 것을 고려해서 배열 크기를 10001로 잡지 않고, 10000 까지만 잡는 경우 발생할 수 있습니다.

 

2. 또 다른 인덱스 에러

입력으로 0이 들어온 경우, 0을 출력해야하는데, 코드에서 이 부분을 처리하지 않으면 python 코드로 로직을 짰을 때 인덱스 에러가 발생할 수 있습니다.

 

3. d 일 안에 오기만 하면 된다는 조건을 d 일째에 가야하는 것으로 착각한 경우 발생할 수 있는 반례가 있습니다.

입력
3
1 1
10 2
10 2
정답 20

입력
3
70 3
60 3
50 3
정답 180

입력
4
70 3
60 3
50 3
40 3
정답 180

입력
4
20 2
30 2
40 3
40 3
정답 110