백준 웹사이트 "1463번 - 1로 만들기" 문제풀이입니다.
언어는 C언어입니다. (제출 언어: C99)

문제
1463번: 1로 만들기
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
www.acmicpc.net
소스 코드
#include <stdio.h> int min(int a, int b); int main(void){ int N; scanf("%d", &N); int num[N+1]; //num[n]: n을 1로 만드는 데 필요한 연산의 횟수 num[0]=0, num[1]=0; //printf("num[%d]: %d\nnum[%d]: %d\n", 0, num[0], 1, num[1]); for(int i=2; i<=N; i++){ int minimum = num[i-1] + 1; if(i%3==0){ minimum = min(minimum, num[i/3]+1); } if(i%2==0){ minimum = min(minimum, num[i/2]+1); } num[i] = minimum; //printf("num[%d]: %d\n", i, num[i]); } printf("%d\n", num[N]); } int min(int a, int b){ if(a<b) return a; else return b; }
문제 풀이
'num[n]'은 숫자 n을 1로 만드는 데 필요한 연산의 횟수입니다. 동적 계획법을 이용하여 각 수를 1로 만드는 연산의 횟수를 기록하는 것이 핵심이며, 점화식은 다음과 같습니다.
숫자 i에 대해 num[i]를 구하기 위해, num[i-1], num[i/3], num[i/2]를 비교하여 그 중 최솟값에 1을 더하면 되는 셈이죠. 하지만 이 점화식에 틀린 점이 있습니다. 바로 num[i/3]과 num[i/2]는 각각 i가 3으로 나누어떨어질 때, i가 2로 나누어 떨어질 때만 고려해줘야 한다는 것입니다. 이러한 조건까지 고려하여, 아래와 같이 동적 계획법을 시행하면 됩니다.
for(int i=2; i<=N; i++){ int minimum = num[i-1] + 1; if(i%3==0){ minimum = min(minimum, num[i/3]+1); } if(i%2==0){ minimum = min(minimum, num[i/2]+1); } num[i] = minimum; //printf("num[%d]: %d\n", i, num[i]); }
위와 같은 for문을 거치면, 배열 'num'에는 각 숫자를 1로 만드는 연산 횟수의 최솟값이 저장됩니다. 마지막으로 정수 N을 1로 만드는 연산 횟수의 최솟값은 'num[N]'을 출력함으로써 얻을 수 있습니다.
반응형
'코딩 > 백준 BOJ' 카테고리의 다른 글
[백준/C언어] 2156번 - 포도주 시식 (0) | 2022.03.11 |
---|---|
[백준/C언어] 10844번 - 쉬운 계단 수 (0) | 2022.03.10 |
[백준/C언어] 2579번 - 계단 오르기 (0) | 2022.03.08 |
[백준/C언어] 1932번 - 정수 삼각형 (0) | 2022.03.07 |
[백준/C언어] 1149번 - RGB거리 (0) | 2022.03.06 |