내가 제일 어려워하는 dp 문제들 중 쉬운 편에 속하는 문제이다.
나는 이것도 못풀었지만 최백준 님의 강의를 통해 dp 문제를 해결하는데
대충은 감을 잡은 것 같다.
dp문제는 작은문제들로 큰문제를 해결하는 것이라고 한다.
1로 만들기 문제를 통해 다시 한번 정리해 볼 것이다.
n을 1로 만들때의 최소값을 구하기 위해
1, 2, 3 ,4 ... n까지의 최소값을 전부 구해야한다.
원래 나는 처음부터 n의 최소값을 구하는 알고리즘을 짜곤 했었는데
그건 dp에대한 이해가 부족한 것이었다.
문제에서는 1로만들 수 있는 세가지 방법을 알려준다.
1. 3으로 나누어떨어질 때는 나누기 3
2. 2로 나누어떨어질 때는 나누기 2
3. 빼기 1
3으로 나누어떨어진다고 해서 무조건 3부터 나눠버리는게 1로 만드는 최소값이 아니다.
n = 10이 그 예외이다.
최소값을 저장할 배열을 dp로 만들었다면
dp[0] = 0
dp[1] = 0
으로 초기화 한다. 0과 1일땐 따로 연산이 필요하지 않다.
그리고 문제 그대로 n/2했을 때 n/3했을 때 n-1 했을 때
가장 최소값인 것을 찾아서 dp배열에 넣어주면 된다.
가장 작은 값부터 차례대로 최소값을 구했다면
n번째 값을 구할 때 n이 3으로 나누어 떨어진다면
dp[n/3] 번째 값에 n/3을 연산한 횟수 1만 더해주면 될 것이다.
결국 이 문제는 dp[n/3]+1, dp[n/2]+1, dp[n-1]+1 중 최소값을 찾아서
dp[n]에 넣어주면 되는 문제였다.
dp[2]부터 차근차근 최소값을 넣어주면 dp[n]을 구할 수 있다.
나는 dp초보이기 때문에 우선 내가 편한 Bottom-Up방식으로 푸는법에 익숙해질 생각이다.
Bottom-Up 방식
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.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; //n이 나누어떨어지는 것과 관계없는 n-1을 일단 dp[i]에 넣어둔다.
}
System.out.println(dp[n]);
}
|
Top-Down 방식
1
2
3
4
5
6
7
8
9
10
|
static int oneCreate(int n, int[] dp) {
if(n==1) return 0;
if(dp[n] > 0) return dp[n];
dp[n] = oneCreate(n-1, dp) + 1;
if(n%2 == 0)
if(n%3 == 0)
return dp[n];
}
|
'Algorithm' 카테고리의 다른 글
백준 9095 1, 2, 3 더하기 Java (0) | 2019.04.09 |
---|---|
백준 11726 2xn 타일링 Java (0) | 2019.04.09 |
백준 1406 에디터 Java (0) | 2019.04.08 |
백준 10799 쇠막대기 Java (2) | 2019.04.08 |
백준 10951 A+B - 4 Java (0) | 2019.04.08 |