코딩테스트/BOJ

[BOJ] 12852 1로 만들기 2 - JAVA

5월._. 2023. 6. 13.
728x90

1. 문제

 

12852번: 1로 만들기 2

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 자연수 N이 주어진다.

www.acmicpc.net

정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.

1. X가 3으로 나누어 떨어지면, 3으로 나눈다.
2. X가 2로 나누어 떨어지면, 2로 나눈다.
3. 1을 뺀다.


정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.


2. 풀이

Bottom-up(dp)

1.  N에서 1로 만드는 경우의 수를 dp에 저장한다.

  -    dp[i]를 먼저 dp[i-1]+1로 저장한 뒤, dp[i/2]+1,dp[i/3]+1과 비교해서 더 작은 값이 있다면 교체한다.

2.  dp[N]부터 시작해서 dp[N]-1값과 같은 숫자를 찾아 StringBuilder에 더한다.

import java.io.*;
import java.util.*;

public class BOJ_12852_1로만들기2 {
   public static void main(String[] args) throws IOException {
      int N = Integer.parseInt(new BufferedReader(new InputStreamReader(System.in)).readLine());

      int[] dp = new int[N+1];
      dp[1] = 0;
      for(int i=2;i<=N;i++){
         dp[i] = dp[i-1]+1;
         if(i%3==0) dp[i] = Math.min(dp[i], dp[i/3]+1);
         if(i%2==0) dp[i] = Math.min(dp[i], dp[i/2]+1);
      }

      StringBuilder sb = new StringBuilder();
      sb.append(dp[N]).append('\n').append(N).append(' ');
      int num = N;
      while(num!=1){
         if(num%3==0 && dp[num/3]==dp[num]-1) num = num/3;
         else if(num%2==0 && dp[num/2]==dp[num]-1) num = num/2;
         else num = num-1;
         sb.append(num).append(' ');
      }

      System.out.print(sb);
   }
}

 

Top-down(bfs)

BFS를 같이 활용해서 dp에 저장한다. queue에 N을 넣고 하나씩 뽑아서 탐색한다. N부터 시작해서 1까지 탐색하기 때문에 dp[1]이 연산을 사용하는 횟수의 최솟값이다.

int[] dp = new int[N+1];
Queue<Integer> queue = new ArrayDeque<>();
queue.offer(N);
int num;
while(!queue.isEmpty()){
   num = queue.poll();
   if(num<=1) break;
   if(num%3==0 && dp[num/3]==0){
      queue.offer(num/3);
      dp[num/3] = dp[num]+1;
   }
   if(num%2==0 && dp[num/2]==0){
      queue.offer(num/2);
      dp[num/2] = dp[num]+1;
   }
   if(dp[num-1]==0){
      queue.offer(num-1);
      dp[num-1] = dp[num]+1;
   }
}

 

dp가 채워졌다면 N->1로 가는 경로를 출력하기 위해 answer배열을 채워야 한다. dp[1]+1사이즈의 배열을 만들어서 경로를 저장한다. 이때 N부터 시작하기 위해 dp[1]-1부터 0 순서로 채운다.

dp[num]-1이 dp[새로운 숫자]와 같다면 이동할 수 있다. num을 교체한다.

마지막에 answer[i]에 num을 저장하고 다음 반복 스텝을 돌린다.

//숫자 채우기
int[] answer = new int[dp[1]+1];
num = 1;
answer[dp[1]] = 1;
for(int i=dp[1]-1;i>=0;i--){
   if(num*3<=N && dp[num*3]==dp[num]-1) num*=3;
   else if(num*2<=N && dp[num*2]==dp[num]-1) num*=2;
   else num+=1;
   answer[i] = num;
}

 

StringBuilder을 이용해서 dp[1]과 answer배열을 출력한다.

//출력
StringBuilder sb = new StringBuilder();
sb.append(dp[1]).append('\n');
for(int n:answer) sb.append(n).append(' ');

System.out.println(sb);

 

전체 코드는 다음과 같다.

import java.io.*;
import java.util.*;

public class BOJ_12852_1로만들기2_2 {
   public static void main(String[] args) throws IOException {
      int N = Integer.parseInt(new BufferedReader(new InputStreamReader(System.in)).readLine());

      int[] dp = new int[N+1];
      Queue<Integer> queue = new ArrayDeque<>();
      queue.offer(N);
      int num;
      while(!queue.isEmpty()){
         num = queue.poll();
         if(num<=1) break;
         if(num%3==0 && dp[num/3]==0){
            queue.offer(num/3);
            dp[num/3] = dp[num]+1;
         }
         if(num%2==0 && dp[num/2]==0){
            queue.offer(num/2);
            dp[num/2] = dp[num]+1;
         }
         if(dp[num-1]==0){
            queue.offer(num-1);
            dp[num-1] = dp[num]+1;
         }
      }

      //숫자 채우기
      int[] answer = new int[dp[1]+1];
      num = 1;
      answer[dp[1]] = 1;
      for(int i=dp[1]-1;i>=0;i--){
         if(num*3<=N && dp[num*3]==dp[num]-1) num*=3;
         else if(num*2<=N && dp[num*2]==dp[num]-1) num*=2;
         else num+=1;
         answer[i] = num;
      }

      //출력
      StringBuilder sb = new StringBuilder();
      sb.append(dp[1]).append('\n');
      for(int n:answer) sb.append(n).append(' ');

      System.out.println(sb);
   }
}

3. 결과

위가 bottom-up, 아래가 top-down방식이다.

'코딩테스트 > BOJ' 카테고리의 다른 글

[BOJ] 1107 리모컨 - JAVA  (0) 2023.06.15
[BOJ] 14940 쉬운 최단거리 - JAVA  (0) 2023.06.14
[BOJ] 12101 1,2,3 더하기 2 - JAVA  (0) 2023.06.12
[BOJ] 15988 1,2,3 더하기 3 - JAVA  (0) 2023.06.11
[BOJ] 1890 점프 - JAVA  (0) 2023.06.10

댓글