import java.util.*;
import java.lang.*;
import java.io.*;
class Main {
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] dp = new int[N+1];
dp[1]=0;
for(int i=2; i<N+1; i++){
int cur = i;
if( i%2 != 0 && i%3 != 0) {
dp[i] = dp[cur - 1] + 1;
}else if(cur%3==0){
int prev = dp[cur/3];
if(cur%2==0){
prev = Math.min(dp[cur/3], dp[cur/2]);
}
dp[i] = Math.min(prev, dp[cur-1]) + 1;
}else if(cur%2==0){
dp[i] = Math.min(dp[cur/2], dp[cur-1]) + 1;
}
}
System.out.println(dp[N]);
}
}
// ✘ 복잡한 if-else 체인
if( i%2 != 0 && i%3 != 0) {
dp[i] = dp[cur - 1] + 1;
}else if(cur%3==0){
int prev = dp[cur/3];
if(cur%2==0){
prev = Math.min(dp[cur/3], dp[cur/2]);
}
dp[i] = Math.min(prev, dp[cur-1]) + 1;
}else if(cur%2==0){
dp[i] = Math.min(dp[cur/2], dp[cur-1]) + 1;
}
모든 경우를 통합하면 더 간결하다.
int cur = i; // i를 그대로 사용 가능
중첩된 조건문으로 로직 파악이 어렵다.
import java.io.*;
class Main {
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] dp = new int[N+1];
for(int i=2; i<=N; i++){
// 기본: 1 빼기
dp[i] = dp[i-1] + 1;
// 2로 나누기
if(i % 2 == 0){
dp[i] = Math.min(dp[i], dp[i/2] + 1);
}
// 3으로 나누기
if(i % 3 == 0){
dp[i] = Math.min(dp[i], dp[i/3] + 1);
}
}
System.out.println(dp[N]);
}
}
변경 사항:
dp[i-1] + 1로 설정| 방법 | 시간복잡도 | 공간복잡도 | 코드 길이 |
|---|---|---|---|
| 원본 | O(N) | O(N) | 25줄 |
| 개선 | O(N) | O(N) | 15줄 |
dp[i] = 1 + min(
dp[i-1], // 1 빼기
dp[i/2] (i%2==0), // 2로 나누기
dp[i/3] (i%3==0) // 3으로 나누기
)
10 → 9 → 3 → 1 (3번) ✔
10 → 5 → 4 → 2 → 1 (4번) ✘
항상 나누기가 최선은 아니다. 모든 경로를 고려해야 한다.
#백준 #DP #동적계획법 #BOJ1463 #Java #알고리즘