seukseok의 개인 블로그

BOJ 풀이 노트: 증가 부분수열 합 DP와 나이트 이동 BFS 점검

· tech

BOJ 11055와 7562를 대상으로, 증가 부분수열 최대 합 DP와 체스판 최단거리 BFS를 실수 포인트 중심으로 실전 정리했다.

오늘은 DP와 그래프 탐색을 하나씩 묶어서 2문제를 풀었다.

11055는 “길이”가 아니라 “합”을 최대화하는 점이 핵심이고, 7562는 가중치 없는 격자 최단거리라 BFS를 정확히 구현하면 안정적으로 풀린다.

1) BOJ 11055 - 가장 큰 증가 부분 수열

문제 핵심 요약

수열에서 증가하는 부분수열을 골랐을 때, 그 원소들의 합이 최대가 되는 값을 구하는 문제다.

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

LIS(최장 증가 부분수열)와 비슷하지만 목적 함수가 길이가 아니라 합이다.

dp[i]를 “i번 원소를 마지막으로 사용하는 증가 부분수열의 최대 합”으로 두면,

이렇게 하면 각 위치를 끝점으로 하는 최적해를 구할 수 있고, 전체 정답은 max(dp[i])가 된다.

시간/공간 복잡도

실수하기 쉬운 포인트

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

dp[i] = a[i];
for (int j = 0; j < i; ++j) {
    if (a[j] < a[i]) {
        dp[i] = max(dp[i], dp[j] + a[i]);
    }
}

“i에서 끝나는 최대 합”을 채우는 핵심 전이다.

answer = max(answer, dp[i]);

i마다 전역 최댓값을 갱신해 최종 정답을 만든다.

다른 풀이 가능성


2) BOJ 7562 - 나이트의 이동

문제 핵심 요약

체스판 크기 L x L에서 나이트가 시작점에서 목표점까지 이동할 때 필요한 최소 이동 횟수를 구하는 문제다.

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

각 칸을 정점으로 보고, 나이트의 8가지 이동을 간선으로 보면 가중치 없는 그래프 최단거리 문제가 된다. 따라서 BFS가 정답이다. BFS는 먼저 도달한 거리가 항상 최소 거리다.

테스트케이스마다 거리 배열을 -1로 초기화하고 시작점을 0으로 두어 탐색했다.

시간/공간 복잡도

실수하기 쉬운 포인트

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

dist[sx][sy] = 0;
q.push({sx, sy});

BFS 시작 상태를 잡는 부분. dist == -1을 미방문으로 사용한다.

if (nx < 0 || nx >= l || ny < 0 || ny >= l) continue;
if (dist[nx][ny] != -1) continue;
dist[nx][ny] = dist[x][y] + 1;
q.push({nx, ny});

경계/방문 검사를 통과한 칸만 확장해 최단거리 성질을 보장한다.

다른 풀이 가능성


오늘 정리 포인트는 두 가지다.

기본기를 이런 식으로 매일 2문제씩 고정 루틴으로 반복하면, 구현 실수 빈도와 풀이 시간이 눈에 띄게 줄어든다.