[Silver III] 1로 만들기 - 1463
성능 요약
메모리: 18092 KB, 시간: 120 ms
분류
다이나믹 프로그래밍
제출 일자
2024년 10월 18일 16:19:04
문제 설명
정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.
- X가 3으로 나누어 떨어지면, 3으로 나눈다.
- X가 2로 나누어 떨어지면, 2로 나눈다.
- 1을 뺀다.
정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.
입력
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
출력
첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.
다음은 문제에 제시된 예시이다.
10의 경우에 10 → 9 → 3 → 1 로 3번 만에 만들 수 있다.
목표는 숫자를 1로 만드는 것이며 각 숫자를 1로 만들기 위한 최소 연산 횟수를 구해보자
2 → 1번 : 2로 나누었을 때 || 1을 뺐을 때
3 → 1번: 3으로 나누었을 때
4 → 2번 : 2로 두번 나누었을 때 || 2로 나누고 1을 뺐을 때
5 → 3번 : 1을 빼고 2로 두번 나누었을 때 || 1을 빼고 2로 나누고 1을 뺐을 때
...
4의 경우 기존 2의 결과에 2로 나눈 연산의 횟수를 추가한 것이며 → 4 / 2 = 2
5의 경우 기존 4의 결과에 1을 뺀 연산의 횟수를 추가한 것이다 → 5 - 1 = 4
결론
1) i-1을 1로 만드는 최소 횟수 + 1 (1을 빼는 연산)
2) i/2를 1로 만드는 최소 횟수 + 1 (2로 나누는 연산, i가 짝수일 때)
3) i/3을 1로 만드는 최소 횟수 + 1 (3으로 나누는 연산, i가 3의 배수일 때)
이를 통해 다음과 같은 코드를 작성할 수 있다
import java.io.*;
import java.util.*;
class Main{
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] dp = new int[Math.max(N+1,4)];
// 2와 3의 최소 연산 횟수를 1로 초기화
dp[2] = 1;
dp[3] = 1;
for(int i=4; i<=N; i++){
// 이전 값에 1을 추가 -> 2로 나누어지지 않고 3으로 나누어지지 않는 경우
// 이전 값 + 1을 한 것이므로
dp[i] = dp[i-1] + 1;
// i가 2로 나누어질 때
if(i%2 == 0){
// 기존에 선언된 dp[i]값과 dp[i/2]를 비교하여 작은 값으로 최신화
dp[i] = Math.min(dp[i], dp[i/2]+1);
}
// i가 3으로 나누어질 때
if(i%3 == 0){
// 기존에 선언된 dp[i]값과 dp[i/3]를 비교하여 작은 값으로 최신화
dp[i] = Math.min(dp[i], dp[i/3]+1);
}
}
System.out.println(dp[N]);
br.close();
}
}
'코딩테스트 > 백준' 카테고리의 다른 글
[Silver II] 좌표 압축 - 18870 (1) | 2024.10.23 |
---|---|
[Gold V] AC - 5430 (1) | 2024.10.20 |
[Gold V] 토마토 - 7576 (1) | 2024.10.17 |
[Gold II] 가운데를 말해요 - 1655 (0) | 2024.10.16 |
[Silver II] 유기농 배추 - 1012 (4) | 2024.09.27 |