-
[DP] 1463번 문제풀이백준 문제풀이/Dynamic Programming 2019. 5. 4. 13:24
문제분석
문제는 이렇습니다.
임의의 숫자를 3가지의 연산을 이용하여 1을 만들고자 할때,
연산횟수의 최솟값은 ?!
1. X가 3으로 나누어 떨어지는 경우, 3으로 나눈다.
2. X가 2로 나누어 떨어지는 경우, 2로 나눈다.
3. X 에 1을 뺀다.
예를 들어, 12이라는 숫자가 주어졌고
같이 1로 만들어 봅시다.
첫번째
12 > 4 > 2 > 1
총 3회
두번째
12 > 6 > 3 > 1
총 3회
이런식으로 3가지의 연산을 사용하면
다양한 경우의 수가 등장합니다.
그러면 이 경우의 수를 모두 따져봅시다.
d[i] = i 를 1로 만드는 최소 연산 횟수
라고 정의합시다.
1. x가 3으로 나누어 떨어지면, 3으로 나눈다.
d[12] = d[12/3] + 1
...더보기현재, 12는 3으로 나누어 떨어지므로
3으로 나눈 값의 최소 횟수에 1을 더한값을 배열에 넣어주는 것입니다.
2. x가 2로 나누어 떨어지면, 2로나눈다.
d[12] = d[12/2] + 1
...더보기12는 2로 나누어 떨어지므로 2로 나눈 값의 최소 횟수에 1을 더한값을
배열에 넣어줍니다.
3. x에 1을 빼준다.
d[12] = d[12 -1] + 1
...더보기11의 최소 횟수에 1을 더해준다.
계속 1을 더해주는 것은 연산을 한번 진행했기 때문인거 아시죠 ?
이제 이 세가지 경우의 최솟 값을 찾아야 합니다.
그런데, 1번, 2번의 경우는 중복되지 않기 때문에
3번이랑만 비교하면 되겠죠 ?
따라서 3으로 나누어 지는 경우는 1번과 3번을 비교하고
2로 나누어지는 경우는 2번과 3번을 비교하면 됩니다.
마지막으로 d[1]의 경우는 0으로 초기화를 해주셔야되요.
1은 이미 1이기 때문에 당연히 연산이 필요없겠죠.
코드
#include <bits/stdc++.h> using namespace std; int d[1000000]; int n; int main(void) { ios::sync_with_stdio(0); cin.tie(0); cin >> n; d[1] = 0; for (int i = 2; i <= n; i++) { d[i] = d[i - 1] + 1; if (i % 2 == 0) d[i] = min(d[i], d[i / 2] + 1); if (i % 3 == 0) d[i] = min(d[i], d[i / 3] + 1); } cout << d[n]; }
'백준 문제풀이 > Dynamic Programming' 카테고리의 다른 글
[DP] BOJ 11053 번 문제 풀이 (0) 2019.05.13 [DP] BOJ 1912 번 문제풀이 (0) 2019.05.11 [DP] BOJ 11726 번 문제 (0) 2019.05.11 [DP] BOJ 1149 번 문제 풀이 (0) 2019.05.06 [DP] BOJ 2579번 문제풀이 (0) 2019.05.04