펭로그

[C++] BOJ 백준 1463 1로 만들기 본문

Study/PS(Algorithm)

[C++] BOJ 백준 1463 1로 만들기

노랑펭귄 2018. 9. 1. 14:54

문제링크 : https://boj.kr/1463


DP를 사용하면 이전 단계의 계산 결과를 그대로 활용할 수 있는 문제이다.

문제에서 힌트로 주어진 10을 연산하는 방법을 생각해보면

10 -> 5 -> 4 -> 2 -> 1

10 -> 9 -> 3 -> 1

이런 방법이 나올 수 있을 것이다.

10이라는 숫자는 바로 2로 나눌 수 있는 숫자이지만 -1을 한 후에 연산하면 횟수가 더 적은 것을 확인할 수 있다.

따라서, 어떤 숫자가 2나 3으로 나눌 수 있을 지라도 -1을 했을 때와 비교한 후 최소 횟수가 어느쪽인지를 취하면 문제를 풀 수 있게 된다.


1을 뺀 후에 연산하는 방법이 어떤 경우에도 허용이 되기 때문에 먼저 1을 빼서 연산한 횟수를 계산한다.

현재 숫자에서 1을 뺀 연산은 이전 단계에서 이미 연산이 되었기 때문에 dp[i-1]에다가 연산 횟수 1회만 추가하면 된다.


그리고 3으로 나누어지거나 2로 나누어지거나 어떤 연산을 우선적으로 해도 상관은 없다.

그 값은 이미 구해져있기 때문이다.

이 역시 dp[i/3]이나 dp[i/2]에다가 연산 횟수 1회만 추가하면 된다.


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
32
33
34
// BOJ 1463 1로 만들기
#include <bits/stdc++.h>
 
using namespace std;
 
int min(int a, int b) {
    return a > b ? b : a;
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    // freopen("../input.txt", "r", stdin);
 
    int num;
    cin >> num;
    vector<int> dp(num + 1);
 
    // 초기 기저 값
    dp[1= 0;
    dp[2= 1;
    dp[3= 1;
    for (int i = 4; i <= num; i++) {
        dp[i] = dp[i - 1+ 1;
        if (i % 3 == 0)
            dp[i] = min(dp[i], dp[i / 3+ 1);
        else if (i % 2 == 0)
            dp[i] = min(dp[i], dp[i / 2+ 1);
    }
    cout << dp[num];
 
    return 0;
}
cs


Comments