문제 해결은 상태 정의에서 시작된다
동적계획법(DP)은 점화식과 관련이 깊다. 하지만 점화식은 상태 간의 관계를 수식화한 결과물에 불과하다.
사실 DP문제가 어려운 점은 그리고 DP 문제의 출발점은 ‘무엇을 상태로 잡을 것인가’라는 결정이다.
DP란 결국 문제를 쪼개어 푸는 방식이다. 그렇다면 먼저 물어야 할 질문은 다음과 같다.
이 문제를 어떤 기준에서 나눌 수 있는가?
그 나눔의 단위를 어떤 상태로 정의할 것인가?
상태란 문제를 구성하는 단위이자 그 단위 간 전이 구조를 정의하는 것이다.
DP를 정확히 이해한다는 것은 문제 상황을 일정한 단위로 나누고 그 단위 간 관계를 수식으로 표현할 수 있는 언어를 구성하는 일이다.
상태 정의는 몇 가지 구조로 나뉜다
▸ 단일 인덱스 기반 상태
- 이 구조에서 ‘상태’는 단 하나의 변수, 즉 진행 인덱스로만 정의된다.
이때 인덱스 는 문제를 구성하는 일련의 단계를 순서대로 따라가고 있다는 의미이다.
중요한 점은, 이전에 어떤 선택이 이루어졌는지에 대한 정보가 전혀 필요하지 않다는 것이다.- 성립 조건
- 이전 상태의 선택 이력이 현재 선택 가능성에 영향을 주지 않아야 한다
즉, 선택의 결과가 오직 현재 위치 만으로 결정되어야 한다. - 전이 조건이
하나로 정의되어야 한다
예:
이 수식은 앞의 두 인덱스에서 상태 값을 받아 현재를 구성한다. 그 외의 조건은 존재하지 않는다.
- 이전 상태의 선택 이력이 현재 선택 가능성에 영향을 주지 않아야 한다
- 예시
피보나치 수열: 현재 항을 만들기 위해 필요한 것은 오직 두 항( , )뿐이다.
LIS 문제: 각 에 대해 보다 작은 들 중 최대 를 찾으면 된다.
이때 가 어떤 경로로 왔는지, 그 이전에 어떤 수들이 선택되었는지는 전혀 중요하지 않다. - 전형적인 오류
상태 만 정의해놓고, 실제로는 전이할 때 ‘최댓값’, ‘이전 선택값’, ‘조건’ 등을 추가로 참조하는 경우
→ 이 경우는 사실상 단일 인덱스 기반이 아니라 이중 인자 기반 상태로 재정의되어야 한다.
- 성립 조건
▸ 이중 인자 기반 상태 (인덱스 + 누적 조건)
여기서 상태는 두 개의 변수로 구성된다. 첫 번째는 여전히 ‘진행 인덱스’
이 두 번째 변수는 현재 상태가 전이 가능한지를 판단하기 위한 제약 조건의 잔여치로 해석된다.
- 성립 조건
- 이전 선택이 남긴 자원 사용량이 이후 선택 가능성에 직접적인 영향을 미쳐야 한다
- 같은 인덱스라도 자원 상태에 따라 전이 결과가 달라져야 한다
→ , 등의 형태가 된다. 이때 는 잔여 무게, 는 잔여 비용 등이 될 수 있다.
- 예시
0/1 배낭 문제:
→ 현재 물건을 고를 수 있는지는 잔여 무게 가 기준이 된다.
제한 경로 탐색: 현재 노드 에 비용 로 도달했을 때의 상태 를 정의함. 다음 노드 로 가는 데 드는 비용 에 따라 전이 가능성이 결정된다. - 오류 지점
전이 조건에서 순회를 잘못 설정하거나, 0/1 배낭에서 같은 물건을 두 번 고르는 실수를 하는 경우
→ 이 경우는 전이 방향을 잘못 구성했거나 상태 정의 자체가 불완전한 것이다.
▸ 조합 기반 상태 (선택 이력 의존형)
이 구조에서는 상태 정의에 현재까지의 선택 집합 또는 이력 정보를 포함해야 한다.
즉, 단일 인덱스나 누적 값으로는 상태를 완전히 식별할 수 없고, 어떤 조합이 선택되었는지를 명시적으로 포함시켜야 한다.
- 성립 조건
- 이전까지의 선택 조합이 이후의 선택 가능성을 결정해야 한다
- 동일한 인덱스라도 선택 이력에 따라 전이 방향과 결과가 달라져야 한다
- 예시
외판원 순회(TSP): 형태의 상태. 는 지금까지 방문한 정점들의 집합, 는 현재 위치한 정점
→ 전이: 아직 방문하지 않은 정점 에 대해
순열 구성: 비트마스크 로 어떤 원소를 이미 선택했는지 표현, 남은 원소의 선택은 에 따라 달라짐 - 주의할 점
상태 공간이 이상으로 커질 수 있음
→ 비트마스크 등의 압축 표현이 필수적이며, 메모이제이션이 없다면 실현 불가
▸ 다차원 인덱스 기반 상태 (이중 진행 축 구조)
문제를 구성하는 두 개의 독립적인 축이 동시에 전개될 때, 두 인덱스를 함께 상태로 포함한다.
여기서 두 인덱스는 단순히 서로 다른 위치가 아니라 서로 다른 차원의 진행 상태이다.
- 성립 조건
- 두 차원의 현재 위치가 모두 필요해야 현재 상황을 완전히 규정할 수 있다
- 전이가 두 축의 위치 조합에 따라 결정되어야 한다
- 예시
최장 공통 부분 수열(LCS): 상태 는 각각 문자열 A, B의 위치
→ 전이: 두 문자가 같으면 대각선 이동, 다르면 좌 또는 상 방향 중 큰 값 선택
격자 DP: 는 격자 좌표, 전이는 또는 에서 결정됨 - 오류 사례
격자 DP에서 와 중 하나만 상태로 정의하거나, 좌표 이동을 혼동하여 불가능한 전이를 시도하는 경우
▸ 구간 기반 상태 (범위 단위 분할 구조)
두 개의 인덱스를 사용하는 경우라도, 이들이 ‘서로 다른 축의 위치’가 아니라 연속된 구간의 양 끝을 나타내는 경우, 상태는 구간 전체를 단위로 정의해야 한다.
- 성립 조건
- 하나의 상태가 특정 구간 [
, ] 전체를 의미해야 한다 - 전이는 이 구간을 중간 지점
에서 분할하고, 양쪽 결과를 결합하는 구조여야 한다
- 하나의 상태가 특정 구간 [
- 예시
행렬 곱셈 최적화:
회문 분할: 문자열 [ , ]이 회문인지 판단하고, 최소 분할 횟수를 계산 - 전이 핵심
전이는 항상 어떤 중간 지점에서 범위를 쪼개고, 두 하위 구간 결과를 병합하는 구조여야 한다.
▸ 트리 기반 상태 (계층 구조 전이)
문제의 대상이 트리 구조를 따르고 전이가 인덱스나 좌표가 아닌 노드 간의 계층 관계를 기반으로 정의된다면 상태는 선형 인덱스가 아니라 노드의 위치와 그 하위 구조에 의해 결정되어야 한다.
이 구조는 다음 조건에서 등장한다:
- 문제의 입력이 트리 구조이며
- 전이가 부모 → 자식 또는 자식 → 부모 방향으로 구조적 흐름을 따를 때
예를 들어, 트리 최대 독립 집합(Tree Maximum Independent Set) 문제를 보자. 각 노드의 선택 여부에 따라 자식 노드의 선택 가능성이 달라지며, 상태는
전이는 다음과 같이 구성된다:
- 부모 노드를 선택하지 않은 경우, 자식 노드를 선택해도 된다
- 부모 노드를 선택한 경우, 자식 노드는 반드시 제외해야 한다
따라서 전이는 단순히 인덱스를 증가시키는 방식이 아니라, 트리의 구조를 따라 전개되는 종속 흐름이다.
또한 서브트리에서 어떤 값을 집계하는 문제들도 이 구조에 포함된다. 예를 들어 서브트리 합, 서브트리 내 최댓값, DFS 순회 기반 DP 등은 항상 자식 → 부모 또는 루트 → 리프 방향의 전이 흐름을 가진다.
상태가 트리 구조상의 노드 단위로 정의되며 전이가 인접한 인덱스가 아닌 계층적 구조 흐름에 따라 전개된다면 트리 기반 상태 정의가 필요하다.
상태 정의는 실패할 수 있다
DP에서 상태는 문제를 나누는 기준이자, 점화식이 성립하기 위한 전제 조건이다. 상태를 제대로 정의하지 못하면 점화식을 구성할 수 없거나, 상태 공간이 과도하게 커지거나 전이 구조가 성립하지 않아 알고리즘 전체가 무너질 수 있다.
실제로 자주 발생하는 상태 정의 실패는 아래 세 가지 유형으로 나뉜다.
오류 유형 | 설명 | 전형적 문제 |
과잉 정의 (over-specified) | 상태에 필요 없는 정보까지 포함해 상태 수만 증가 | |
불완전 정의 (under-specified) | 전이에 필요한 정보가 상태에 누락됨 | 경로 조건이 중요한데 방향 정보가 빠진 경우 |
불안정 정의 (untracked condition) | 특정 조건의 만족 여부가 상태에 반영되지 않음 | “특정 지점을 지난 적 있는가”가 누락된 경우 |
▸ 과잉 정의 (over-specified)
불필요한 정보를 상태에 포함하면 상태 수만 증가하고, 의미는 달라지지 않는다.
이 경우 점화식은 구성되지만 동일한 계산을 여러 상태에서 반복하게 되므로 시간과 공간 효율이 크게 나빠진다.
예시
→ last 값만큼 상태가 중복 생성되며, 점화식의 전이 대상도 불필요하게 많아진다.
▸ 불완전 정의 (under-specified)
전이에 반드시 필요한 정보가 상태에 포함되지 않으면 점화식을 만들 수 없다.
이런 상태는 전이 대상이 명확하지 않기 때문에 점화식이 모호해지거나 구현이 불가능해진다.
예시
격자에서 이동 경로를 계산하는데,
이전에 어떤 방향으로 움직였는지를 알아야 전이 조건이 달라지는 경우
→ 방향 정보가 빠진 상태에서는 그 전이 조건을 판단할 수 없다.
▸ 불안정 정의 (untracked condition)
문제 조건 중에서 ‘특정 조건을 만족한 적이 있는가’와 같은 이력이 전이 조건에 영향을 주는 경우
이 정보가 상태에 반영되지 않으면 전이 결과가 달라질 수 있어 점화식은 잘못된 경로를 따라갈 수 있다.
예시
“출발점에서 반드시 특정 지점을 한 번 이상 지나야 한다” 같은 조건이 있는데 그 지점을 지났는지 여부를 상태에 포함하지 않음
→ 올바른 해를 걸러낼 수 없고, 잘못된 해가 함께 저장된다.
상태 공간은 줄일 수 있어야 한다
상태를 잘 정의했더라도 전체 상태 공간의 크기가 크다면 효율적인 알고리즘을 구성하기 어렵다.
이를 해결하기 위한 대표적인 상태 공간 축소 기법은 다음과 같다.
기법 | 개념 | 요약적용 | 조건예시 |
롤링 배열 (rolling array) | 이전 상태만으로 현재 상태 계산 가능 → 배열 차원 축소 | 전이가 고정폭 참조인 경우 | 피보나치 수열 ( |
대칭성 제거 (symmetry elimination) | 구조상 대칭되는 상태는 하나로 취급 | 무차별 순열, 색상 구분 없음 | 조합 문제에서 좌우 교환 제거 |
지배 제거 (dominance pruning) | 항상 열등한 상태는 제외 | 배낭 문제 등 최적값이 정렬 가능할 때 | 무게는 더 무겁고 가치도 낮은 경우 제거 가능 |
▸ 롤링 배열 (rolling array)
전이가 이전 몇 개의 상태에만 의존한다면 전체 테이블을 만들지 않고 일부만 유지하면 된다.
배열을 순환하거나 교체하며 공간을 줄일 수 있다.
적용 조건
- 전이가 고정폭 참조일 때 (예:
가 , 만 필요)
예시
- 피보나치 수열:
→ 과거 두 개의 값만 유지하면 되므로 을 로 줄일 수 있음
▸ 대칭성 제거 (symmetry elimination)
해가 대칭 구조를 가질 경우, 중복되는 절반의 상태는 계산하지 않아도 된다.
이는 순열, 조합, 색상 구분 없는 문제 등에서 자주 활용된다.
적용 조건
- 상태 공간이 좌우나 순서 등에서 대칭인 구조를 가질 때
예시
- 조합 문제:
개 중 개 선택할 때, 와 는 대칭이므로 한 쪽만 계산 - 색이 구분되지 않는 공을 나누는 문제에서
→ 같은 조합을 다른 순서로 나눈 것을 중복 처리하지 않음
▸ 지배 제거 (dominance pruning)
항상 성능이 낮은 상태는 더 이상 계산할 필요가 없다.
이런 상태는 다른 상태에 비교 열등하므로 DP 테이블에서 제거할 수 있다.
적용 조건
- 문제에서 “이 상태는 다른 상태보다 항상 나쁘다”는 기준을 정할 수 있을 때
예시
- 배낭 문제: 무게가 더 무겁고, 가치도 낮은 상태는
→ 동일한 무게 제한 내에서 더 나은 선택으로 항상 대체 가능하므로 제외
DP는 점화식이 아니라 상태에서 시작된다.
점화식은 상태 정의가 끝난 다음에야 만들 수 있다.
상태가 문제 상황을 정확히 구분하고 그 상태들 사이의 전이 조건이 일관되게 연결될 때 비로소 점화식은 구성 가능하다.
또한, 정의된 상태가 많아지면 이를 줄이는 방법도 필요하다.
전이 방식은 그대로 두고 상태의 표현만 최적화하는 것이 공간 축소 전략이다.
이처럼 동적계획법은 세 가지 단계를 거친다.
① 상태를 정의하고
② 상태 간 관계를 수식으로 표현하며
③ 불필요한 상태를 제거하여 계산을 줄인다.
DP는 계산을 줄이는 기술이 아니라 문제를 분해하고 표현하는 방식의 선택이다.
이 선택은 점화식보다 먼저 내려져야 한다.
'프로그래밍, 코딩 > 알고리즘 및 코딩테스트' 카테고리의 다른 글
완전탐색, 동적계획법, 탐욕 알고리즘을 나누는 조건은 무엇인가? (0) | 2025.05.16 |
---|---|
프로그래머스 - 입국심사 (0) | 2025.04.29 |
baek9461_파도반 수열 (0) | 2025.03.30 |
백준 24267번 : 알고리즘 수업을 통해 보는 삼중 시그마의 이해 (0) | 2025.03.02 |
stack sortable 에 대한 논증 (0) | 2025.02.20 |