[백준] 1463번 - 1로 만들기
문제
문제 설명 및 풀이
DP 문제 중 이런 문제가 제일 편하다고 생각된다. 문제에서 IF 조건을 친절하게 번호까지 붙여가며 알려주기 때문이다. I-1 번째 수에 1을 더한 것이 I 번째 수이므로, 기본적으로 I-1 번째 값에 1을 더한 값이 I 번째 값이다. 그러나, 2와 3으로 나누어떨어진다면 그 수가 더 작아질 경우가 있음으로 확인해주면 된다. 나누어떨어진다면 그 값에 1을 더한 값이 I 번째 값이다. 이것이 맨 처음 내가 떠올린 풀이이다. 근데 막상 제출해보니 메모리와 시간이 다른 사람들의 답보다 한참 높게 나와서 다른 사람들의 코드도 살펴보았다.
바로 재귀를 이용한 풀이다. 현재 위치에 도달하는 최솟값을 리턴하는 함수를 만드는데, 이는 2 또는 3으로 나누어떨어지는 거리(x/2, x/3)와 나머지 거리(x%2, x%3)에 1(무조건 드는 연산 횟수)을 더한 값이다. 둘 중 최솟값이 곧 정답이 된다.
정답 코드
#include <iostream>
#include <algorithm>
using namespace std;
int n;
int dp[1000001] = { 0, };
int main()
{
cin >> n;
for (int i = 2; i <= n; i++)
{
dp[i] = dp[i - 1] + 1;
if (i % 2 == 0)
dp[i] = min(dp[i], dp[i / 2] + 1);
if (i % 3 == 0)
dp[i] = min(dp[i], dp[i / 3] + 1);
}
cout << dp[n] << "\n";
return 0;
}
재귀를 이용한 코드
#include <iostream>
#include <algorithm>
using namespace std;
int n;
int recur(int x)
{
if(x <= 1)
return 0;
return min(recur(x/3) + 1 + x%3, recur(x/2) + 1 + x%2);
}
int main()
{
cin >> n;
cout << recur(n);
return 0;
}