메모리: 79372 KB, 시간: 216 ms
다이나믹 프로그래밍
2024년 8월 25일 22:25:49
정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.
- X가 3으로 나누어 떨어지면, 3으로 나눈다.
- X가 2로 나누어 떨어지면, 2로 나눈다.
- 1을 뺀다.
정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.
풀이
다이나믹 프로그래밍으로 한 번 풀어봤다.
다이나믹 프로그래밍이란 이전의 결과를 저장하고 다음 함수에 사용함으로써, 시간 복잡도를 줄이는 방법이다.
계산 방식은 총 세 가지다
- 3으로 나누기
- 2로 나누기
- 1을 빼기
우리가 코드를 짜며 생각해야할 부분은
3과 2 동시에 나눠질 때 분기를 어떻게 나눌 것인가,
3으로 나눠질 때의 분기를 어떻게 나눌 것인가,
2로 나눠질 때 분기를 어떻게 나눌까 이다.
6으로 나눠 떨어진다면
3으로 나눴을 때 수행 횟수 VS 2로 나눴을 때 수행 횟수 VS -1을 했을 때 수행 횟수를 비교하면 될 것이다.
이와 마찬가지로 다른 분기에도 모두 적용을 시키고 코드를 짜보면 다음과 같이 코드를 작성할 수 있다.
전체 코드
public class Main {
public static void main(String args[])throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int N = Integer.parseInt(br.readLine());
int[] dp = new int[N+1];
for(int i = 0 ;i<=N;i++){
dp[i] = -1;
}
dp[0] = dp[1] = 0;
int k = cur(N,dp);
bw.write("" + k);
bw.flush();
}
public static int cur(int N, int dp[]){
if(dp[N] == -1) {
if(N % 6 == 0){
dp[N] = Math.min(cur(N/3,dp), Math.min(cur(N/2,dp), cur(N-1,dp)))+1;
}
else if (N % 3 == 0) {
dp[N] = Math.min(cur(N-1,dp),cur(N / 3, dp))+1;
return dp[N];
} else if (N % 2 == 0) {
dp[N] = Math.min(cur(N/2,dp),cur(N-1,dp))+1;
return dp[N];
}
else{
dp[N] = cur(N-1,dp)+1;
return dp[N];
}
}
return dp[N];
}
}
'백준' 카테고리의 다른 글
백준 11053번 가장 긴 증가하는 부분수열 (java) (0) | 2024.08.27 |
---|---|
백준 18353번 병사 배치하기 (java) (LIS 알고리즘) (0) | 2024.08.27 |
백준 19621번 회의실 배정 (java) (0) | 2024.08.18 |
백준 5567번 결혼식 (java) (0) | 2024.08.18 |
백준 14496번 그대, 그머가 되어 (java) (0) | 2024.08.16 |