DP 테이블
DP 테이블
요
DP 테이블Dynamic Programming Table)은 동적획법(Dynamic Programming, DP) 구현할 때 사용하는 데이터 구조로, 주로 1차원 또는 2원 배열 형태로 표현된다. DP는 복잡한 문제를 작은 하위 문제로 나누어 해결한 후, 그 결과를 저장하고 재사용함으로써 중복 계산을 피하고 효율적으로 최적해를 도출하는 알고리즘 기법이다. 이 과정에서 중간 결과를 저장하는 것이 핵심이며, 이 역할을 수행하는 것이 바로 DP 테이블**이다.
DP 테이블은 문제의 구조에 따라 다양한 형태를 가질 수 있으며, 문제 해결 과정에서 상태(state)를 인덱스로 하여 해당 상태에서의 최적값이나 경우의 수를 저장한다. 예를 들어, 피보나치 수열, 배낭 문제(Knapsack), 최장 공통 부분수열(LCS) 등의 문제에서 DP 테이블은 필수적인 구성 요소로 사용된다.
DP 테이블의 원리
동적 계획법의 기본 개념
동적 계획법은 다음과 같은 두 가지 성질을 만족하는 문제에 적용할 수 있다:
- 부분 문제 중복(Overlapping Subproblems): 동일한 하위 문제가 여러 번 반복되어 호출됨.
- 최적 부분 구조(Optimal Substructure): 전체 문제의 최적해가 하위 문제의 최적해로부터 구성될 수 있음.
이러한 성질을 가진 문제에서는, 하위 문제의 결과를 DP 테이블에 저장함으로써 반복 계산을 방지하고 시간 복잡도를 크게 줄일 수 있다.
DP 테이블의 역할
DP 테이블은 다음과 같은 역할을 수행한다:
- 상태 저장: 각 하위 문제의 해를 저장한다.
- 계산 최적화: 저장된 값을 재사용하여 중복 계산을 방지한다.
- 경로 추적: 최적해를 구성하는 경로를 역추적할 수 있도록 정보를 유지할 수 있음 (예: LCS 문제).
DP 테이블의 구현 예시
1. 피보나치 수열
피보나치 수열은 가장 기본적인 DP 예제 중 하나이다.
F(n) = F(n-1) + F(n-2)
이며, F(0)=0
, F(1)=1
이다.
def fibonacci(n):
dp = [0] * (n + 1)
dp[0] = 0
dp[1] = 1
for i in range(2, n + 1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
✅ 이 경우 DP 테이블은 1차원 배열이며, 각 인덱스가 문제의 상태를 나타낸다.
2. 0-1 배낭 문제 (Knapsack Problem)
무게 제한이 있는 배낭에 물건을 담아 가치를 최대화하는 문제.
n
개의 물건, 각각 무게w[i]
, 가치v[i]
- 배낭의 최대 무게:
W
- DP 테이블:
dp[i][w]
= 첫i
개의 물건 중 무게w
이하로 담을 수 있는 최대 가치
def knapsack(weights, values, W):
n = len(weights)
dp = [[0] * (W + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for w in range(W + 1):
if weights[i-1] <= w:
dp[i][w] = max(
dp[i-1][w],
dp[i-1][w - weights[i-1]] + values[i-1]
)
else:
dp[i][w] = dp[i-1][w]
return dp[n][W]
dp[i][w]
는 2차원 DP 테이블의 한 요소로, 상태 전이(state transition)를 명확히 표현한다.- 시간 및 공간 복잡도: O(nW)
✅ 이 경우 DP 테이블은 2차원 배열이며, 두 개의 상태(물건 수, 무게)를 동시에 고려한다.
3. 최장 공통 부분수열 (LCS)
두 문자열의 최장 공통 부분수열의 길이를 구하는 문제.
X
,Y
문자열dp[i][j]
:X[0..i-1]
과Y[0..j-1]
의 LCS 길이
def lcs(X, Y):
m, n = len(X), len(Y)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for in range(1, n + 1):
if X[i-1] == Y[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return dp[m][n]
dp[i][j]
는 두 문자열의 접두사 간 LCS 길이를 저장한다.- 이후 역추적을 통해 실제 부분수열도 복원 가능.
DP 테이블의 최적화 기법
공간 최적화 (Space Optimization)
일부 문제에서는 DP 테이블의 전체 이력을 저장할 필요가 없으며, 이전 단계의 정보만으로 충분하다.
예: 피보나치 수열
→ dp[i]
는 dp[i-1]
과 dp[i-2]
만 필요하므로, 배열 전체 대신 두 변수로 충분.
def fibonacci_optimized(n):
if n <= 1:
return n
a, b = 0, 1
for _ in range(2, n + 1):
a, b = b, a + b
return b
- 공간 복잡도: O(1)
누적합 DP
일부 문제에서는 DP 테이블이 누적합 형태로 사용되며, 예를 들어 구간 합 쿼리 문제에서는 누적합 배열이 일종의 DP 테이블로 간주될 수 있다.
prefix_sum[0] = 0
for i in range(1, n+1):
prefix_sum[i] = prefix_sum[i-1] + arr[i-1]
참고 자료 및 관련 문서
💡 DP 테이블은 단순한 배열 이상의 의미를 가지며, 문제의 상태 공간을 체계적으로 탐색하는 도구이다. 효과적인 DP 테이블 설계는 알고리즘 성능 향상의 핵심이다.
이 문서는 AI 모델(qwen-3-235b-a22b-instruct-2507)에 의해 생성된 콘텐츠입니다.
주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.