개발아 담하자

[백준/C++]1463번 : 1로 만들기 풀이 본문

👩‍💻 알고리즘 풀이/백준

[백준/C++]1463번 : 1로 만들기 풀이

choidam 2020. 1. 22. 00:30

문제 1463 : 1로 만들기

문제 링크 : https://www.acmicpc.net/problem/1463

 

1463번: 1로 만들기

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

www.acmicpc.net

 

 

문제

 

정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.

  1. X가 3으로 나누어 떨어지면, 3으로 나눈다.
  2. X가 2로 나누어 떨어지면, 2로 나눈다.
  3. 1을 뺀다.

정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.

 

입력

 

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

 

출력

 

첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.

 

 

 

위 문제는 BFS, DP 모두 접근이 가능하다.

 

<1> BFS 풀이

- 미로탐색 (https://www.acmicpc.net/problem/2178) 과 비슷하게 접근하면 쉽다.

- 입력한 수 n 이 1 에 도달하는 최단 경로를 구한다고 생각하면 간단하게 BFS 로 접근이 가능하다.

 

#include <iostream>
#include <queue>

using namespace std;

int main(void){

    int n;
    cin >> n;
    
    queue<pair<int,int>> que;
    que.push(make_pair(n, 0));
    
    while(!que.empty()){
        int num = que.front().first;
        int cnt = que.front().second;
        
        if(num==1) break;
        
        que.pop();
        
        if(num-1>=0) que.push(make_pair(num-1, cnt+1));
        if(num%3==0) que.push(make_pair(num/3, cnt+1));
        if(num%2==0) que.push(make_pair(num/2, cnt+1));
    }
    
    cout << que.front().second << endl;
   
    return 0;
}

 

 

 

 

<2> DP 풀이

- BFS 보다 DP 로 접근하면 더욱 간단하게 문제를 풀 수 있다.

- d[i] = min(d[i/2]+1, d[i/3]+1, d[i-1]+1) 공식으로 2부터 n까지 차근차근히 구한다.

 

#include <iostream>

const int MAX = 1000001;
using namespace std;

int min(int a, int b){
    return a < b ? a : b;
}

int main(void){
    int n, d[MAX];
    cin >> n;
    
    d[1] = 0;
    
    for(int i=2; i<=n; i++){
        d[i] = d[i-1] + 1;
        if(i%2 == 0) d[i] = min(d[i/2]+1, d[i]);
        if(i%3 == 0) d[i] = min(d[i/3]+1, d[i]);
    }
    
    cout << d[n] << endl;
    return 0;
}

 

BFS 로 접근했을 때 보다 DP 접근이 메모리와 시간이 훨씬 절약됨을 알 수 있다 ‼️