seukseok의 개인 블로그

BOJ 풀이 노트: DP와 BFS 기본기 점검

· tech

BOJ 14501, 1697을 문제 핵심, 접근 이유, 복잡도, 실수 포인트, 핵심 코드 라인과 대안 풀이 관점으로 정리한 실전 노트.

오늘은 유형이 다른 두 문제를 묶어서 풀었다.

하나는 일정 선택형 DP, 다른 하나는 최단 시간 탐색 BFS다. 둘 다 코딩 테스트에서 자주 재등장하는 기본 패턴이라 루틴 점검용으로 좋았다.

1) BOJ 14501 - 퇴사

문제 핵심 요약

N일 동안 상담 일정이 주어지고, 각 상담은 소요 일수 T[i]와 수익 P[i]를 가진다. 퇴사일(N+1일) 전까지 상담을 겹치지 않게 선택해 최대 수익을 구하는 문제다.

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

매일 “오늘 상담을 한다 / 안 한다” 선택이 생기고, 오늘의 선택이 미래 가능한 상태를 바꾼다. 이 구조는 전형적인 DP다.

이 방식이면 겹침 처리와 퇴사일 초과 검사를 자연스럽게 함께 처리할 수 있다.

시간/공간 복잡도

실수하기 쉬운 포인트

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

dp[day + 1] = max(dp[day + 1], dp[day]);
int endDay = day + T[day];
if (endDay <= N + 1) {
    dp[endDay] = max(dp[endDay], dp[day] + P[day]);
}

다른 풀이 가능성

뒤에서 앞으로 가는 역방향 DP(dp[i] = max(dp[i+1], P[i] + dp[i+T[i]]))도 가능하다. 핵심은 동일하게 “상담 선택 vs 스킵” 비교다.


2) BOJ 1697 - 숨바꼭질

문제 핵심 요약

수빈이의 위치 N에서 동생 위치 K까지 가는 최소 시간을 구한다. 한 번에 할 수 있는 이동은 x-1, x+1, 2*x다.

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

모든 이동 비용이 1초로 동일하므로, 최단 시간은 BFS로 구하는 것이 정석이다.

가중치가 모두 같다는 점이 다익스트라보다 BFS를 쓰는 이유다.

시간/공간 복잡도

실수하기 쉬운 포인트

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

vector<int> dist(MAX + 1, -1);
dist[N] = 0;
q.push(N);
int nextPos[3] = {cur - 1, cur + 1, cur * 2};
for (int nx : nextPos) {
    if (nx < 0 || nx > MAX) continue;
    if (dist[nx] != -1) continue;
    dist[nx] = dist[cur] + 1;
    q.push(nx);
}

다른 풀이 가능성

양방향 BFS를 적용해 탐색 폭을 줄일 수는 있지만, 이 문제 범위에서는 일반 BFS만으로도 충분히 통과 가능하고 구현 실수도 적다.


오늘 정리 포인트:

전형 문제를 꾸준히 정리해두면, 실전에서 풀이 선택 자체가 빨라진다.