🖥️ CS/Baekjoon Algorithms

#1463번 1로 만들기 (C++)

한국의 메타몽 2020. 5. 20. 14:12
#include <iostream>
#include <algorithm>
using namespace std;

int dp[1000001];

int solve(int n){
    for(int i=2; i<=n; i++){
        dp[i] = dp[i-1] + 1;
        if(i%3==0) dp[i] = min(dp[i],dp[i/3]+1);
        if(i%2==0) dp[i] = min(dp[i],dp[i/2]+1);
    }
    return dp[n];
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int N = 0;
    cin >> N;

    dp[1] = 0, dp[0] = 0;
    cout << solve(N);

    return 0;
}

min기능은 구현하지 않고 STL을 사용했다. 

우선 단계별로 코드를 설명하다면 하단과 같다. 

 

1. dp[i] = dp[i-1] + 1; ---> -1을 실행해서 1로 만드는 경우

: 숫자 '4'를 예시로 들어보자. '4'를 1로 만드는 방법은 나누기 2를 두번 걸치면 된다. 

다른 방법으로도 1을 만들 수 있지만, 어찌되었건 공통적으로 토탈 과정은 '2'번을 거쳐서 1이 나온다. 

그 다음 번째 숫자인 '5'를 1로 만든다고 가정해보자.

2를 나누냐 3을 나누냐를 떠나서, 4를 1로 만드는 과정에서 +1을 더해주면 5가 나오기 때문이다. 


2. if(i%3==0) dp[i] = min(dp[i],dp[i/3]+1); ---> 3을 나누어 1로 만드는 경우

: 바로 윗줄에서 가장 간단한 '1'을 빼는 방식을 시행했다. 

다음으로 해당 숫자가 3으로 나눠지는지 판단해본다. 

나눠지면 -1을 해서 얻는 결과 vs 숫자를 3으로 나눈 뒤 +1하는 결과를 따져서 최소값을 기입해준다. 

왜 dp[i/3] + 1인가? 이는 1번의 논리와 같다. 

(1) 3으로 나눈다는 1개의 과정을 추가하여

(2) 3으로 나눠버린다음

(3) 3으로 나눴을 때 나오는 값의 과정의 합을 그대로 더해주기 때문이다. 

 

3. if(i%2==0) dp[i] = min(dp[i],dp[i/2]+1); ---> 2를 나누어 1로 만드는 경우

이는 2번과 같은 논리이다. 

 

이렇게 3가지 과정을 비교해서 최소값이 출력되는 로직이 완성된다. 

'🖥️ CS > Baekjoon Algorithms' 카테고리의 다른 글

#1920번 수 찾기 (C++)  (0) 2020.05.22
#2960번 에라토스테네스의 체 (C++)  (0) 2020.05.20
#2579번 계단 오르기 (C++)  (0) 2020.05.18
#1149번 RGB거리 (C++)  (0) 2020.04.29
#9461번 파도반 수열 (C++)  (0) 2020.04.28