Date:

1) 문제 링크

https://www.acmicpc.net/problem/1463

2) 접근

X와 X/2, X/2, X-1의 관계를 줬다는 점에서 DP 문제라는 생각이 들었다. 이후 연산 횟수의 최솟값을 기록하는 cnt 배열을 만들고, 최솟값을 갱신해 나가는 방식으로 코드를 짰다. 시간복잡도는 O(n)이다.

3) 풀이

#include <iostream>
using namespace std;

int main(void){
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    int N;

    cin >> N;

    int cnt[N+1] = {0, };

    cnt[1] = 0;
    cnt[2] = cnt[3] = 1;

    for(int i=2; i<N; ++i){
        if(i*3 <= N && (!cnt[i*3] || cnt[i*3] > cnt[i] + 1)) { cnt[i*3] = cnt[i] + 1; }
        if(i*2 <= N && (!cnt[i*2] || cnt[i*2] > cnt[i] + 1)) { cnt[i*2] = cnt[i] + 1; }
        if(i+1 <= N && (!cnt[i+1] || cnt[i+1] > cnt[i] + 1)) { cnt[i+1] = cnt[i] + 1; }
    }

    cout << cnt[N];

    return 0;
}

4) 피드백

아직 종만북을 제대로 안 보긴 했지만… 애초에 DP는 for로 돌리는 것 외에도 재귀함수를 이용하는 방법도 있다. 그리고, 무작정 돌리는 것보다 재귀로 돌리는 게 실행 시간을 대폭 감소시킬 수도 있다. 메모이제이션까지 더한다면 더더욱.

30124463번 코드는 이 문제를 재귀함수를 이용하여 해결한 예이다. 일단 2 이상의 자연수면 나누기 연산을 이용해야만 최적해가 도출된다는 것을 이용해 삼항 연산자에 2가지 case를 담았고, 나머지 연산을 사용함으로써 배수 여부에 관계없이 재귀 가능하게 했다는 것이 특징이다. 이런 거 보고 배워야겠당.

Leave a comment