seukseok의 개인 블로그

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

· boj-note

오늘은 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문제씩 고정 루틴으로 반복하면, 구현 실수 빈도와 풀이 시간이 눈에 띄게 줄어든다.