어떤 문제를 푸는가
수열이나 구간을 다룰 때, "구간 \([l, r]\)의 답"을 그 안의 어떤 경계 \(k\)에서
둘로 쪼개 작은 구간의 답으로 정의하는 DP입니다. 행렬 곱셈 순서, 돌 합치기,
팰린드롬 분할 같은 "어디서 나눌까/합칠까"가 핵심인 문제에 쓰입니다.
상태와 점화식의 골격
$$ dp[l][r] = \text{구간 } [l, r] \text{을 처리하는 최적 비용} $$
길이 1(또는 0) 구간은 기저로 직접 채우고, 더 긴 구간은 가능한 분할점 \(k\)를
모두 시도해 최적을 고릅니다.
$$ dp[l][r] = \min_{l \le k < r} \bigl( dp[l][k] + dp[k+1][r] + (\text{합치는 비용}) \bigr) $$
"합치는 비용"은 문제마다 다릅니다(예: 두 묶음의 합, 행렬 곱셈의 연산 수).
예 — 돌 합치기 / 파일 합치기
연속한 두 묶음을 합치는 비용이 "두 묶음 크기의 합"일 때, 전부 하나로 합치는
최소 비용을 구합니다. 구간 \([l, r]\)의 합 \(S(l, r)\)은 누적 합으로 \(O(1)\)에
구하고,
$$ dp[l][r] = \min_{l \le k < r} \bigl( dp[l][k] + dp[k+1][r] \bigr) + S(l, r) $$
마지막 합치기 비용 \(S(l, r)\)은 어디서 나누든 동일하게 더해집니다.
왜 옳은가
최적해의 구조를 보면, 구간 \([l, r]\)을 최종적으로 만드는 마지막 합치기/분할
이 어딘가의 경계 \(k\)에서 일어납니다. 그 \(k\)로 나눈 두 부분은 각각 자신의
최적해여야 합니다(아니면 전체를 개선할 수 있으므로). 모든 \(k\)를 시도하면 그중
진짜 최적 경계가 포함되므로 최적 부분 구조가 성립합니다.
채우는 순서 — 길이 오름차순
dp[l][r]은 자기보다 짧은 구간들에 의존합니다. 따라서 구간 길이를 1부터
키워 가며 채워야 의존하는 값이 먼저 준비됩니다.
for len = 2..n:
for l = ...:
r = l + len - 1
dp[l][r] = min over k
복잡도
구간 쌍 \(O(N^2)\)개, 각 구간마다 분할점 \(O(N)\)이므로
$$ O(N^3) $$
\(N \le 400 \sim 500\) 정도에서 현실적입니다. 사각 부등식이 성립하면
크누스 최적화로 \(O(N^2)\)까지 줄일 수 있습니다(상위 단원).
신호 잡기
"구간을 어디서 나눌까/합칠까", "양 끝에서 어떻게 좁힐까"가 문제의 본질이고
\(N\)이 수백 규모면 구간 DP를 의심하세요. 다음 강의에서 구현과 변형을 봅니다.