본문 바로가기
자료구조&알고리즘/동적 프로그래밍

[이.코.테] Chapter 08 동적 프로그래밍 - 1로 만들기 (java)

by _din 2020. 11. 6.

1로 만들기 (교재 217p)

난이도 ●◐○ | 풀이 시간 20분 | 시간 제한 1초 | 메모리 제한 128MB

 

문제정수 X가 주어질 때 정수 X에 사용할 수 있는 연산은 다음과 같이 4가지이다.

  1. X가 5로 나누어떨어지면, 5로 나눈다.
  2. X가 3으로 나누어떨이지면, 3으로 나눈다.
  3. X가 2로 나누어떨어지면, 2로 나눈다.
  4. X에서 1을 뺀다.

정수 X가 주어졌을 때, 연산 4개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.

 

입출력 조건)

입력 조건  첫째 줄에 정수 X가 주어진다. (1 ≤ X ≤ 30,000)
출력 조건  첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.

입출력 예시)

입력 예시 출력 예시
26 3

 


문제 풀이 방법

 

X=6일 때, 호출되는 과정

 

이 문제를 점화식으로 표현해보면 아래와 같다.

$a_{i}=min(a_{i-1},a_{i/2},a_{i/3},a_{i/5})+1$

 

소스 코드

package exam08_dynamic_programming;

import java.io.*;

public class Q1_MakeOne {
    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 x = Integer.parseInt(br.readLine());

        int[] a = new int[x+1];

        a[1] = 0;
        a[2] = 1;

        for (int i = 3; i < a.length; i++) {
            a[i] = a[i-1] + 1; // 일단, 1을 뺀다. 그리고 1을 뺀 연산을 한 횟수 1을 더한다.

            /* 각각 5 또는 3 또는 2로 나누어지는 경우,
             *  1을 뺀 것과 바로 나누어 연산했을 때의 횟수를 비교하여 최솟값을 저장한다.
             * 
             * 5,3,2 모두 나누어질 경우도 있으므로, else if를 사용하지 않고
             *  if를 사용함으로써 저장되어있는 값과 해당 연산의 최솟값을 비교한다.
             * */
            if (i % 5 == 0)
                a[i] = Math.min(a[i], a[i / 5] + 1);

            if (i % 3 == 0)
                a[i] = Math.min(a[i], a[i / 3] + 1);

            if (i % 2 == 0)
                a[i] = Math.min(a[i], a[i / 2] + 1);

        }

        bw.write(a[x]+"\n");

        br.close();
        bw.close();
    }
}
반응형

댓글