티스토리 뷰

알고리즘/C

백준 1463번 1로 만들기 C언어

지휘리릭 2019. 9. 27. 18:57

문제

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

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

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

입력

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

출력

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

 

 

 

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
void solution(int num, int cnt) {
    if (num == 1) {
        if (cnt < cnt_min) {
            cnt_min = cnt;
        }
    }
    else {
        if (num % 3 == 0) {
            cnt++;
            solution((num / 3), cnt);
            cnt--;
        }
        if (num % 2 == 0) {
            cnt++;
            solution((num / 2), cnt);
            cnt--;
        }
        if (num > 1) {
            cnt++;
            solution(num - 1, cnt);
            cnt--;
        }
    }
}

 

2.

http://blog.naver.com/PostView.nhn?blogId=occidere&logNo=220787315353 이 블로그를 참고했다.

그래서  배열을 만들어서 풀었다.

프로그래머스 사이트에서 푼 쿠키 구입이랑 비슷한건 아닌데 응용되는 유형인 것 같다.

https://iamthejiheee.tistory.com/30

 

프로그래머스 쿠키 구입 C언어

1. 무작정 for문을 돌려봤는데 정말 시간 복잡도가 쉣이ㅏ다. 아예 cookie 배열에서 n번째까지의 합을 따로 sum이라는 배열에 저장했다. 그러면 첫째 아들은 sum[m] - sum[l] 둘째 아들은 sum[r] - sum[m+1] 을 가..

iamthejiheee.tistory.com

3. 아래와 같은 규칙을 갖는다.

N이 가지는 최소 횟수

(1) N이 3으로 나누어 떨어질 경우 :  (N/3)이 가지는 최소 횟수 + 1

(2) N이 2로 나누어 떨어질 경우 : (N/2) 이 가지는 최소 횟수 + 1

(3) 3이나 2로 나누어 떨어지지 않는 경우 : (N-1)이 가지는 최소 횟수 + 1

 

4. 예시 ) N이 10인 경우

 

(1) N_arr[2] : 1

    [1] 2로 나누어 떨어지는 경우, 1을 빼는 경우 => N_arr[1] + 1 => 1

(2) N_arr[3] : 1

    [1] 3으로 나누어 떨어지느 경우 => N_arr[1] + 1 => 1

    [2] 1을 빼는 경우 => N_arr[2] + 1 => 2

(3) N_arr[4] : 2

    [1] 2로 나누어 떨어지는 경우 => N_arr[2] + 1 => 2

    [2] 1을 빼는 경우 => N_arr[3] + 1 => 3

(4) N_arr[5] : 4

    [1] 1을 빼는 경우 => N_arr[4] + 1 => 4

(5) N_arr[6] : 2

    [1] 3으로 나누어 떨어지는 경우 => N_arr[2] + 1 => 2

    [2] 2로 나누어 떨어지는 경우 => N_arr[3] + 1 => 2

    [3] 1을 빼는 경우 => N_arr[5] + 1 => 5

(6) N_arr[7] : 3

    [1] 1을 빼는 경우 => N_arr[6] + 1 => 3

(7) N_arr[8] : 3

    [1] 2로 나누어 떨어지는 경우 => N_arr[4] + 1 => 3

    [2] 1을 빼는 경우 => N_arr[7] + 1 => 4

(8) N_arr[9] : 2

    [1] 3으로 나누어 떨어지는 경우 => N_arr[3] + 1 => 2

    [2] 1을 빼는 경우 => N_arr[8] + 1 => 4

(9) N_arr[10] : 

    [1] 2로 나누어 떨어지는 경우 => N_arr[5] + 1 => 5

    [2] 1을 빼는 경우 => N_arr[9] + 1 => 3

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
#include<stdio.h>
#define SZ 1000001
#define MIN(a,b) ( a < b ? a : b);
 
int N;
int N_arr[SZ];
 
 
void solution() {
    N_arr[0= N_arr[1= 0;
    int temp;
    for (int i = 2; i <= N; i++) {
        N_arr[i] = N_arr[i - 1+ 1;
        if (i % 3 == 0) {
            temp = N_arr[i / 3+ 1;
            N_arr[i] = MIN(N_arr[i], temp);
        }
        if (i % 2 == 0) {
            temp = N_arr[i / 2+ 1;
            N_arr[i] = MIN(N_arr[i], temp);
        }
    }
    printf("%d", N_arr[N]);
}
 
int main() {
    scanf("%d"&N);
    solution();
}
댓글