일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- 배열
- 다리 만들기
- SQL
- 탐색
- 새벽코딩
- Python
- DP
- BFS
- 시뮬레이션
- LIS
- Java
- 구현
- 빅데이터
- Queue
- 알고리즘
- HashMap
- 프로그래머스
- 백트래킹
- BufferedReader
- 문자열
- dfs
- 완전탐색
- oracle
- 다이나믹프로그래밍
- 그리디
- 스택
- 브루트포스
- Stack
- 백준
- 아스키코드
- Today
- Total
새벽코딩
[백준] [1463] 1로 만들기 (JAVA) (dp) 본문
https://www.acmicpc.net/problem/1463
1463번: 1로 만들기
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
www.acmicpc.net
0.15 초 (하단 참고) | 128 MB | 278129 | 93963 | 59877 | 32.751% |
문제
정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.
- X가 3으로 나누어 떨어지면, 3으로 나눈다.
- X가 2로 나누어 떨어지면, 2로 나눈다.
- 1을 뺀다.
정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.
입력
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
출력
첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.
※ JAVA 코드 (1로 만들기)
import java.io.*;
import java.util.*;
public class Main {
static int[] dp;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
dp = new int[10000001];
System.out.println(dp(n));
}
public static int dp(int n) {
dp[1] = 0;
for(int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + 1;
if(i % 2 == 0) {
dp[i] = Math.min(dp[i], dp[i / 2] + 1);
}
if(i % 3 == 0) {
dp[i] = Math.min(dp[i], dp[i / 3] + 1);
}
}
return dp[n];
}
}
※ 생각정리 (1로 만들기)
1. dp 문제를 풀기위해서는 생각하는 힘을 길러야한다.
2 . 피보나치 수열을 생각해보자
1, 1, 2, 3, 5, 8, 13, 21, 34 ......
n번째 수를 구한다고 하였을때 dp[n] = dp[n-2] + dp[n-1]과 같은 점화식을 세울 수 있다. 그렇다면 왜 이 문제를 풀기전에 이런 것을 설명하는 것이 궁금할 것이다.
이 문제 또한 임의의 숫자 n이 주어졌을 때 해당 숫자를 1로 만드는 과정에서 여러 숫자를 거치게 되고 해당 숫자 인덱스 위치의 배열에 그 숫자를 구하기 위한 최소값을 담아두면 빠르게 해결 할 수 있다. 이해가 안되신다면 다음 설명을 확인해주세요
우리는 1이라는 숫자를 1로 만들기 위해서는 0번의 횟수가 최소값이 되기에 dp[1] = 0 이라 할 수 있다.
그렇다면 2라는 숫자를 1로 만들기 위해서 즉, dp[2]? 두가지 경우의 수가 있다.
1) 2 -1 = 1
2) 2 / 2 = 1
위의 경우에는 둘다 1번의 과정으로 끝나기 때문에 비교를 해줄 필요가 없지만 로직상 우리는 저 횟수를 dp배열에 담아둔다.
dp[2] = Math.min(dp[1] + 1, dp[2 / 2] + 1);
dp[i / 2] + 1은 예를들어 현재의 위치가 dp[10]의 값을 구해야할때 해당 값은 dp[5] + 1의 숫자일 수 있다는 것을 의미한다. 5 * 2 = 10 는 1번의 과정이 추가된 것이므로 + 1.
이렇게 차례대로 dp[2] ~ dp[n]까지의 숫자를 모두 구한다.
최종적으로 1부터 우리가 구해야하는 n이 만들어 지는 최소값은 dp[n]에 담겨있게 된다.
- 새벽 코딩-
'알고리즘' 카테고리의 다른 글
[백준] [1932] 정수 삼각형 (JAVA) (dp) (2) | 2023.10.13 |
---|---|
[백준] [11726] 2 x n 타일링 (JAVA) (dp) (0) | 2023.10.11 |
[백준] [2839] 설탕 배달 (JAVA) (dp) (3) | 2023.10.10 |
[프로그래머스] 연속 부분 수열 합의 개수 (JAVA) (level2) (2) | 2023.10.09 |
[프로그래머스] N개의 최소공배수 (JAVA) (level2) (1) | 2023.10.08 |