일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 30 | 31 |
- 그래프 이론
- C++
- MySQL
- 딥러닝
- Python
- Reinforcement Learning
- 머신러닝
- AlexNet
- dynamic programming
- opencv
- machine learning
- IN
- 강화학습
- image processing
- 백준
- sklearn
- Mask Processing
- 자료구조
- dfs
- 인공지능
- classification
- canny edge detection
- clustering
- MinHeap
- SIFT
- edge detection
- DP
- BFS
- exists
- TD
- Today
- Total
JINWOOJUNG
[ DP - 1463 ] 1로 만들기(C++) 본문
접근법
점화식을 이끌어 내야 하는 중요한 문제이다.
단순히 3으로 나눠지고 2로 나눠진다고 해서 해당 값으로 나누는 연산을 진행 시 최소값을 찾을 수 없게 된다.
이러한 DP문제는 직접 규칙을 찾아보는 것이 가장 중요하다.
연산이 가능한 것을 고려하였을 때 2와 3은 1번의 연산으로 1로 만들 수 있다. 이는 1일 때는 1로 만드는데 0번의 연산이 걸리는 점을 고려하고 넘어가자.
4는 2로 나누어 떨어지기에 2로 나눈 값인 2는 1번의 연산이 더 필요하다.
또한, 1을 먼저 빼고 3으로 나누어도 동일하게 1로 만들 수 있다.
5는 2와 3 모두 나누어 떨어지지 않는다. 따라서 1을 뺀 후 4는 2가지 방법으로 총 2번의 연산을 통해 1로 만들 수 있다.
6은 2와 3으로 모두 나누어 떨어진다. 2로 나누면 3이고, 3은 1번의 연산으로 1로 만들 수 있다.
혹은 1을 먼저 빼고 난 값이 5이고, 5는 다시 1을 뺀 후 4로 만들어 4에서 1로 가는 2번의 연산을 진행하면 1로 만들 수 있다. 하지만 최소값은 2와 3 모두로 나누어 떨어지기에 둘 중 하나의 값으로 나누는 연산 과정에서 구할 수 있다.
여기서 규칙을 찾아보자면 오른쪽 형광색을 주의깊게 살펴보자. 2 혹은 3으로 나누어 떨어지면, 해당 값으로 나눈 후 각 값에서 요구되는 횟수 + 1의 연산이 최종적으로 요구된다.
만약 나누어 떨어지지 않는다면, 1을 뺀 값에 대한 연산 횟수 + 1의 연산이 최종적으로 요구된다.
이를 수식적으로 표현 해 보자. 각 숫자에 따른 연산 횟수를 DP라는 배열에 저장되어 있다고 해 보자.
$DP[2] = DP[1] +1$
$DP[3] = DP[1] +1 , DP[3] = DP[2] + 1 ->$ 이 둘 중 더 작은 값이 최종적인 결과이다.
$DP[4] = DP[4/2] + 1$
$DP[5] = DP[5-1] + 1$
이렇게 표현하면 점화식을 충분히 세울 수 있을 것이다. 3에 대해서는 2가지 방법이 있다. 3으로도 나누어 떨어지지만, 1을 뺀 값에 대한 연산 횟수에서 +1을 한 경우. 따라서 이 모든것을 고려한 후 최소값을 찾아야 한다.
따라서 전체적인 알고리즘은 먼저 1을 뺀 값에 대한 연산 횟수 + 1로 연산 횟수를 설정하고, 2와 3으로 나누어 떨어지는 경우에 대해여 연산 횟수를 비교하여 최소값을 찾으면 된다.
정답
#include<iostream>
#include<algorithm>
using namespace std;
int32_t ars32_DP[1000000];
int main()
{
int32_t s32_Input, s32_I;
cin >> s32_Input;
ars32_DP[1] = 0;
for (s32_I = 2; s32_I <= s32_Input; s32_I++)
{
// 1 빼기
ars32_DP[s32_I] = ars32_DP[s32_I - 1] + 1;
if (s32_I % 3 == 0)
{
ars32_DP[s32_I] = min(ars32_DP[s32_I], ars32_DP[s32_I / 3] + 1);
}
if (s32_I % 2 == 0)
{
ars32_DP[s32_I] = min(ars32_DP[s32_I], ars32_DP[s32_I / 2] + 1);
}
}
printf("%d\n", ars32_DP[s32_Input]);
return 0;
}
'백준' 카테고리의 다른 글
[ DP - 1003 ] 피보나치 함수 (0) | 2024.03.30 |
---|---|
[ DP - 9095 ] 1, 2, 3 더하기 (1) | 2024.03.29 |
[ DP - 2839 ] 설탕 배달(C++) (0) | 2024.03.24 |
[ 28217 ] 두 정삼각형(C++) (0) | 2024.03.24 |
[ 그래프 이론 - 24444 ] 알고리즘 수업 - 너비 우선 탐색 1 (0) | 2024.03.19 |