Skip to main content

Command Palette

Search for a command to run...

[boj] 1202 보석 도둑

Updated
3 min read

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

시간 초과로 고생을 좀 했다...

문제

세계적인 도둑 상덕이는 보석점을 털기로 결심했다.

상덕이가 털 보석점에는 보석이 총 N개 있다. 각 보석은 무게 Mi와 가격 Vi를 가지고 있다. 상덕이는 가방을 K개 가지고 있고, 각 가방에 담을 수 있는 최대 무게는 Ci이다. 가방에는 최대 한 개의 보석만 넣을 수 있다.

상덕이가 훔칠 수 있는 보석의 최대 가격을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000)

다음 N개 줄에는 각 보석의 정보 Mi와 Vi가 주어진다. (0 ≤ Mi, Vi ≤ 1,000,000)

다음 K개 줄에는 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci ≤ 100,000,000)

모든 숫자는 양의 정수이다.

출력

첫째 줄에 상덕이가 훔칠 수 있는 보석 가격의 합의 최댓값을 출력한다.

예제 입력 1

2 1
5 10
100 100
11

예제 출력 1

10

예제 입력 2

3 2
1 65
5 23
2 99
10
2

예제 출력 2

164

풀이

처음에는 간단한 정렬 문제인 줄 알았는데 시간 초과로 상당히 고생했다.

처음 접근법 - 시간 초과

처음에는 높은 가치를 가진 보석을 기준으로 가장 가벼운 무게의 가방을 찾아서 넣으려고 했다. 이렇게 되면 각 보석마다 넣을 수 있는 가방까지 순회를 하면서 찾아야 하므로 시간 복잡도가 O(N^2) (N과 K의 최댓값이 동일함)이 되어 시간 초과로 실패를 했다.

import sys
import heapq

input = sys.stdin.readline
N, K = list(map(int, input().split()))
# 보석 (무게, 가치) 리스트 - 가치 순으로 정렬
gems = sorted([tuple(map(int, input().split())) for _ in range(N)], key=lambda x: x[1])
# 가방 무게 제한 리스트
bags = sorted([int(input()) for _ in range(K)])

answer = 0
candidateBags = []

while bags and gems:
    weight, value = heapq.heappop(gems)
    for i in range(len(bags)):
        if bags[i] >= weight:
            bags = bags[:i] + bags[i + 1 :]
            answer += value
            break
print(answer)

성공한 풀이

성공한 풀이에서는 현재 가방에 넣을 수 있는 보석이면 이 가방보다 더 많은 무게를 견딜 수 있는 가방에도 넣을 수 있다는 사실을 파악하는 것이 가장 중요했다. 이것을 확인한 후로는 하위 문제들의 최적의 해를 바탕으로 최종적인 답을 도출해낼 수 있는 구조이므로 그리디를 통해서 문제를 풀 수 있다.

이를 통해서 가장 작은 가방부터 확인을 하면 한 번 확인한 보석을 다시 가방에 넣을 수 있는지 없는지 확인하지 않아도 되므로 loop 안에 시간 복잡도가 O(N + K)가 되어 정렬에 드는 시간이 가장 큰 영향을 미치게 되어 최종적인 시간 복잡도가 O(NlogN) 되어 시간 초과 없이 문제를 해결할 수 있게 된다.

import sys
import heapq

input = sys.stdin.readline
N, K = list(map(int, input().split()))
# 보석 (무게, 가치) 리스트 - 무게 순으로 정렬
gems = sorted(
    [tuple(map(int, input().split())) for _ in range(N)],
    key=lambda x: x[0],
    reverse=True,
)
# 가방 무게 제한 리스트
bags = sorted([int(input()) for _ in range(K)])

answer = 0
candidateGemValues = []
for bag in bags:
    while gems and bag >= gems[-1][0]:
        _, value = gems.pop()
        # 현재 가방에 넣을 수 있는 높은 가치 순으로 정렬
        heapq.heappush(candidateGemValues, -value)
    if candidateGemValues:
        # 이전 가방은 현재 가방보다 제한이 낮았으므로
        # 이전 가방에 넣을 수 있는 보석은 현재 가방에도 넣을 수 있음
        answer += -1 * heapq.heappop(candidateGemValues)
print(answer)

More from this blog

오픈소스 기여모임 10기 후기 - 첫 Pr을 올리기까지

개발자라면 누구나 한 번쯤 오픈소스 기여에 대한 환상을 가져본 적 있을 거다. 하지만 막상 시작하려면 어디서부터 해야 할지 막막하고, 괜히 대단한 걸 해야 할 것 같은 부담감에 선뜻 시작하기는 어려운 것 같다. 나 또한 해보고 싶다는 마음만 가지고 계속 미뤄왔다. 그러다 2025년 말 쯤에 오픈채팅방과 글또 슬랙 채널에서 "오픈소스 기여모임" 10기 모집글을 봤다. 2년 넘게 500명 이상의 참가자와 함께 1000개 이상의 PR을 만들어온 커뮤...

Feb 5, 20265 min read

😢 글또 10기 활동 회고 — “글또야, 가지 마…”

들어가며 드디어 글또 10기 활동 회고를 정리해본다.6개월간의 여정을 뒤돌아보니 정말 많은 일들이 있었다. 글또라는 커뮤니티를 8기가 한창 진행되고 있을 때 알았는데 이름부터 인상이 강렬했다. "글쓰는 또라이가 세상을 바꾼다." 유쾌하고 독특한 문구에 피식 웃으며, '여긴 도대체 어떤 사람들이 모이는 곳이지?' 하고 넘겼었다. 재밌는 건 결국, 나도 그 "또라이들" 중 한 명이 되었다는 것이다. 😌 글또는 개발자들이 2주에 한 번 글을 ...

Jul 31, 20255 min read
😢 글또 10기 활동 회고 — “글또야, 가지 마…”

Serverless 환경에서 배포 전 환경변수 검증 자동화하기: TypeBox와 Bitbucket Pipeline 활용기

들어가며 배포 직후, 환경변수가 제대로 설정되지 않아 여러 API가 제대로 작동하지 않는 일이 있었습니다. 다행히 밤에 사용자가 없을 때 문제가 있었던 거라 영향도는 크지 않았지만 앞으로도 계속해서 발생할 수 있는 문제이기 때문에 해결해야 겠다고 생각했습니다. 개발 단계에서 문제가 발견되면 가장 좋겠지만, 현재 팀 상황에서는 백엔드 개발을 혼자 담당하고 있어 코드 리뷰나 검증 프로세스를 갖추기가 쉽지 않았습니다. 그래서 최소한 배포 전에 자동으...

Mar 16, 20254 min read

Cloudflare Tunnel로 포트포워딩 없이 홈서버 운영하기

이 글에서 다루는 내용 포트포워딩이 안 되는 이유 (CGNAT 환경 이해) CGNAT 우회 방법들의 장단점 비교 Cloudflare Tunnel 설정 방법 (MacOS 기준) 외부에서 내 PC로 접근할 수 있도록 허용하는 방법을 생각하면 포트포워딩이 가장 먼저 떠오릅니다. 공유기에서 특정 포트를 열어 외부에서 서버에 접속할 수 있도록 설정하는 방식으로, 마인크래프트 멀티를 해보셨던 분이라면 분명 해보셨을 방법입니다. 😊 작년에 저는 홈서...

Mar 2, 20256 min read
Cloudflare Tunnel로 포트포워딩 없이 홈서버 운영하기

구름고래 공방

48 posts