BOJ 1463
2020-03-30
위 문제는 백준 사이트의 알고리즘 1463 문제에 관한 설명입니다.
문제
정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.
X가 3으로 나누어 떨어지면, 3으로 나눈다. X가 2로 나누어 떨어지면, 2로 나눈다. 1을 뺀다. 정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.
입력
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
출력
첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.
### 초기에 작성했던 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int count = 0;
while(N != 1)
{
if(N % 3 ==0)
N/=3;
else if(N % 2 ==0)
N/=2;
else
N-=1;
count++;
System.out.println(N);
}
System.out.println(count);
}
}
처음에는 바로 위 코드 처럼 “3으로 나누거나 2로 나누거나 아니라면 -1시킨다” 라고 생각을 했습니다.
그러나 이렇게 하면 10을 입력했을 때
10 -> 5 -> 4 -> 2-> 1로 4가 출력이 됩니다.
그러나 정답은
10 -> 9 -> 3-> 1로 3이 출력 되어야 합니다.
### 최종 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner =new Scanner(System.in);
int N = scanner.nextInt();
int dp[] = new int[N+1];
dp[0] = 0;
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);
}
System.out.println(dp[N]);
}
}
Bottom-up 방식이라고 하는데 다음번엔 Top-down 방식으로도 풀어봐야겠습니다.
2와 3을 예시로 들어봅시다.
그렇다면
if(i%2==0) dp[i] = Math.min(dp[i], dp[i/2]+1);
에서 dp2과 dp2/2+1(1)이기에 min값인 1이 dp[2]에 저장됩니다.
dp[3]도 같은 과정 입니다.
if(i%3==0) dp[i] = Math.min(dp[i], dp[i/3]+1);
dp[3]은 dp3와 dp3/3+1의 값으로 결정이 되는데
이때 dp[3/3] +1은 1과 같으므로 2보다 값이 작아서 dp[3]에는 1이 저장됩니다.