소스코드
1로 만들기
문제
문제 정의
- 정수 X가 주어질 때 정수 X에 사용할 수 있는 연산은 다음과 같이 4가지이다.
- X가 5로 나누어떨어지면, 5로 나눈다.
- X가 3으로 나누어떨어지면, 3으로 나눈다.
- X가 2로 나누어떨어지면, 2로 나눈다.
- X에서 1을 뺀다.
- 정수 X가 주어졌을 때, 연산 4개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.
- 예시
- 정수가 26이라면 다음과 같이 계산해서 3번의 연산이 최솟값이다.
- 26 - 1 = 25
- 25 / 5 = 5
- 5 / 5 = 1
입력조건
출력조건
- 첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.
입·출력 예시
풀이
문제 해설
- 문제를 풀기 전에 함수가 호출되는 과정을 그림으로 그려보자. 이는 아래와 같다.
- 이것을 점화식으로 표현하면 아래와 같다.
- : 현재 숫자
- : 현재 숫자 i를 만들기 위해 필요한 최소 연산 횟수
소스코드
package dp;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class 만들기_1로 {
static int[] d = new int[30001];
/**
* Bottom Up 방식
*/
private static int bottomUp(int x) {
for (int i = 2; i <= x; i++) {
d[i] = d[i-1] + 1;
if (i % 2 == 0) {
d[i] = Math.min(d[i], d[i / 2] + 1);
}
if (i % 3 == 0) {
d[i] = Math.min(d[i], d[i / 3] + 1);
}
if (i % 5 == 0) {
d[i] = Math.min(d[i], d[i / 5] + 1);
}
}
return d[x];
}
/**
* Top Down 방식
*/
private static int topDown(int x) {
if (x == 1) {
return 0;
}
if (d[x] != 0) {
return d[x];
}
d[x] = topDown(x-1) + 1;
if (x % 5 == 0) {
int tmp = topDown(x/5) + 1;
if (d[x] > tmp) {
d[x] = tmp;
}
}
if (x % 3 == 0) {
int tmp = topDown(x/3) + 1;
if (d[x] > tmp) {
d[x] = tmp;
}
}
if (x % 2 == 0) {
int tmp = topDown(x/2) + 1;
if (d[x] > tmp) {
d[x] = tmp;
}
}
return d[x];
}
public static void execute() throws Exception {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
int x = Integer.parseInt(bf.readLine());
// int answer = bottomUp(n);
int answer = topDown(x);
System.out.println(answer);
}
}
본 게시글은 위 교재를 기반으로 정리한 글입니다.