BOJ 1695 팰린드롬 만들기
BOJ 1695 팰린드롬 만들기
문제
- 주어진 수열에 최소 개수의 숫자를 삽입하여 팰린드롬으로 만들기.
- 수열의 길이 $N \le 5,000$, 각 원소 $\le 10,000$.
- 시간 제한 2초, 메모리 제한 128MB.
복잡도 분석
- Time Complexity: $O(N^2)$
- $N=5,000$일 때 중첩 반복문을 통해 약 $2,500$만 번의 연산을 수행하므로 2초 내에 충분히 통과 가능합니다.
- Space Complexity: $O(N^2)$
int dp[5001][5001]배열은 약 $95.37$ MiB를 차지합니다. 문제의 제한인 128MB 내에 안정적으로 포함됩니다.
접근법
핵심은 “현재 구간 $[i, j]$가 팰린드롬이 되기 위한 최적해는 하위 구간의 해로부터 도출된다”는 점입니다.
1. 상태 정의
$dp[i][j]$를 수열의 $i$번째부터 $j$번째까지를 팰린드롬으로 만들기 위한 최소 삽입 횟수로 정의합니다.
2. 점화식
- 양 끝이 같을 때 ($v[i] == v[j]$):
- $dp[i][j] = dp[i+1][j-1]$ (추가 비용 없음)
- 양 끝이 다를 때 ($v[i] \neq v[j]$):
- 왼쪽에 $v[j]$와 같은 값을 삽입: $1 + dp[i][j-1]$
- 오른쪽에 $v[i]$와 같은 값을 삽입: $1 + dp[i+1][j]$
- $dp[i][j] = \min(dp[i][j-1], dp[i+1][j]) + 1$
3. 계산 순서 (Dependency)
dp[i][j]를 구하기 위해서는 아래(i+1)와 왼쪽(j-1)의 정보가 필요하므로, j는 증가하고 i는 감소하는 순서로 채워야 합니다.
graph TD
subgraph "DP Table Dependency"
node_ij["dp[i][j]"]
node_left["dp[i][j-1]"]
node_down["dp[i+1][j]"]
node_diag["dp[i+1][j-1]"]
node_left -.-> node_ij
node_down -.-> node_ij
node_diag -.-> node_ij
end
풀이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <bits/stdc++.h>
using namespace std;
int dp[5001][5001];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int N; cin >> N;
vector<int> v;
for(int i = 0; i < N; i++) {
int x; cin >> x;
v.push_back(x);
}
// j는 오른쪽으로, i는 왼쪽(아래)에서 위로 올라오며 채움
for(int j = 1; j < N; j++) {
for(int i = j - 1; i >= 0; i--) {
if (v[i] == v[j]) {
dp[i][j] = dp[i + 1][j - 1];
} else {
dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;
}
}
}
cout << dp[0][N - 1];
return 0;
}
비슷한걸 봐서 잘 풀었음
This post is licensed under CC BY 4.0 by the author.
