BOJ C++ 알고리즘 공부
[DP] 1로 만들기 (1463)(C++)
kk_eezz
2024. 1. 22. 17:01
1. 문제 개요
정수 N이 주어졌을 때, N이 3으로 나누어 떨어지면 3으로 나누기, 2로 나누어 떨어지면 2로 나누기, N에서 1을 빼기, 이렇게 세 가지의 연산을 사용하여 N을 최대한 빠르게 1로 만드는 문제이다. 사용한 연산의 최솟값을 구한다.
2. 입출력
3. 문제 풀이
다이나믹 프로그래밍을 통해 주어진 수를 1로 만들 수 있는 연산의 조합 중 최솟값을 구한다. 예를 들어, 주어진 수가 10인 경우, 10은 5에 2를 곱하거나, 9에 1을 더하여 만들 수 있다. 그렇다면 10이 1이 되는 최솟값은 숫자 5가 1이 되는 연산의 최솟값+1과 숫자 9가 1이 되는 연산의 최솟값 둘 중에 더 작은 값을 채택하면 된다. 이를 수식으로 나타내면 다음과 같다.
count[10] = min(count[9]+1, count[5]+1);
이때 count[9]와 count[5] 또한 동일한 방식으로 구하면 되는데, 재귀함수를 사용할 수 있다.
재귀함수 구현은 다음과 같이 할 수 있다.
const int max_val = 1000002;
int number_count(int n) {
if(n==1)
return 0;
else if(count_list[n]!=0)
return count_list[n];
int three_value = max_val;
int two_value = max_val;
int one_value = max_val;
if (n>=3 && n%3==0)
three_value = number_count(n/3) + 1;
if (n>=2 && n%2==0)
two_value = number_count(n/2) + 1;
one_value = number_count(n-1) + 1;
count_list[n] = min(min(three_value, two_value),one_value);
return count_list[n];
}
4. 전체 코드
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
int count_list[1000001];
const int max_val = 1000002;
int number_count(int n) {
if(n==1)
return 0;
else if(count_list[n]!=0)
return count_list[n];
int three_value = max_val;
int two_value = max_val;
int one_value = max_val;
if (n>=3 && n%3==0)
three_value = number_count(n/3) + 1;
if (n>=2 && n%2==0)
two_value = number_count(n/2) + 1;
one_value = number_count(n-1) + 1;
count_list[n] = min(min(three_value, two_value),one_value);
return count_list[n];
}
int main(void) {
int N;
scanf("%d",&N);
printf("%d",number_count(N));
}
아직 배워가는 중이라 틀린 부분이 있을 수 있습니다. 지적할 부분이 있다면 댓글로 알려주시면 감사하겠습니다!!!