seukseok의 개인 블로그

BOJ 풀이 노트: 배낭 DP와 절댓값 힙 구현 점검

· tech

BOJ 12865와 11286을 1차원 배낭 DP와 사용자 정의 비교자 우선순위 큐 관점에서 실전적으로 정리한 풀이 노트.

오늘은 DP 1문제 + 자료구조 1문제로 루틴을 구성했다.

두 문제 모두 정석 패턴을 정확히 구현하면 안정적으로 통과된다. 핵심은 12865에서의 역순 순회 이유, 11286에서의 우선순위 정의를 코드로 명확히 고정하는 것이다.

1) BOJ 12865 - 평범한 배낭

문제 핵심 요약

물건마다 무게와 가치가 주어질 때, 최대 허용 무게 K를 넘지 않으면서 얻을 수 있는 가치 합의 최댓값을 구하는 0/1 배낭 문제다. 각 물건은 최대 1번만 선택 가능하다.

접근 아이디어(왜 이 방법인지)

완전탐색은 경우의 수가 커서 비효율적이다. 이 문제는 전형적인 0/1 Knapsack이라 DP가 정석이다.

dp[cap] = cap 무게 한도에서 가능한 최대 가치로 두고, 각 물건 (w, v)를 보며 다음처럼 갱신한다.

여기서 핵심은 cap큰 값에서 작은 값으로 역순 순회하는 점이다. 그래야 같은 물건이 한 라운드에서 중복 사용되지 않는다(0/1 조건 유지).

시간/공간 복잡도

실수하기 쉬운 포인트

C++ 코드 설명(핵심 라인)

for (int cap = K; cap >= w; --cap) {
    dp[cap] = max(dp[cap], dp[cap - w] + v);
}

한 물건을 처리할 때 역순으로 갱신해 0/1 조건을 보장하는 핵심 루프다.

vector<int> dp(K + 1, 0);

기본값 0은 “아무 물건도 선택하지 않은 상태”를 의미해 초기화가 자연스럽다.

다른 풀이 가능성


2) BOJ 11286 - 절댓값 힙

문제 핵심 요약

정수 x가 주어질 때,

절댓값이 같다면 **더 작은 실제 값(음수 우선)**을 먼저 꺼내야 한다.

접근 아이디어(왜 이 방법인지)

삽입/삭제가 반복되고, 매번 “우선순위가 가장 높은 원소”가 필요하므로 우선순위 큐가 적합하다.

다만 기본 priority_queue 정렬 기준으로는 문제 조건(절댓값 우선, 동률 시 실제값 작은 쪽 우선)을 표현할 수 없어서, 사용자 정의 비교자를 사용한다.

비교 규칙:

  1. abs(a) < abs(b)이면 a가 우선
  2. abs(a) == abs(b)이면 a < b가 우선

시간/공간 복잡도

실수하기 쉬운 포인트

C++ 코드 설명(핵심 라인)

if (aa == bb) return a > b;
return aa > bb;

절댓값 기준 최소 힙 + 동률 시 실제값 최소 힙 동작을 만들기 위한 비교자 핵심이다.

if (x == 0) {
    if (pq.empty()) cout << 0 << '\n';
    else { cout << pq.top() << '\n'; pq.pop(); }
}

문제의 질의 규칙을 그대로 반영한 처리 분기다.

다른 풀이 가능성


오늘 정리 포인트:

정석 패턴 2개를 확실히 손에 익혀두면, 이후 변형 문제에서도 구현 속도와 정확도를 동시에 챙길 수 있다.