728x90
백준 1463번: 1로 만들기
📌 문제
정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.
1. X가 3으로 나누어 떨어지면, 3으로 나눈다.
2. X가 2로 나누어 떨어지면, 2로 나눈다.
3. 1을 뺀다.
정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다.
연산을 사용하는 횟수의 최솟값을 출력하시오.
입력
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
출력
첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.
📝 아이디어
이 문제를 해결하기 위해 동적 프로그래밍(DP)을 사용합니다. 동적 프로그래밍은 복잡한 문제를 간단한 여러 개의 작은 하위 문제로 나누어 효율적으로 해결하는 방법입니다.
우선, DP 테이블을 정의합니다. $dp[i]$는 숫자 $i$를 1로 만들기 위한 최소 연산 횟수를 저장합니다. 예를 들어 $dp[10] = 3$이면 숫자 10을 1로 만드는 데 필요한 최소 연산 횟수가 3이라는 뜻입니다.
숫자 1은 이미 1이므로 추가적인 연산이 필요 없으므로 $dp[1] = 0$으로 설정합니다.
숫자 $i$를 1로 만들기 위해 세 가지 연산을 시도합니다.
- 1을 빼는 경우: $dp[i] = dp[i-1] + 1$
- 2로 나누는 경우 (단, $i$가 2로 나누어떨어질 때): $dp[i] = dp[i//2] + 1$
- 3으로 나누는 경우 (단, $i$가 3으로 나누어떨어질 때): $dp[i] = dp[i//3] + 1$
숫자 $i$에서 가능한 연산들 중 최소값을 선택합니다.
$$dp[i] = \min (dp[i-1], dp[i//2] (\text{if divisible by 2}), dp[i//3] (\text{if divisible by 3}))+1$$
👩💻 나의 답안
n = int(input())
dp = [0] * (n+1)
dp[1] = 0
for i in range(2, n+1):
if i % 6 == 0:
dp[i] = min(dp[i-1], dp[i//3], dp[i//2]) + 1
elif i % 3 == 0:
dp[i] = min(dp[i-1], dp[i//3]) + 1
elif i % 2 == 0:
dp[i] = min(dp[i-1], dp[i//2]) + 1
else:
dp[i] = dp[i-1] + 1
print(dp[n])
$i$가 6으로 나누어떨어지는 경우는 $i$가 2와 3 모두로 나누어떨어진다는 뜻입니다. $i % 2$와 $i % 3$이 모두 가능하므로 두 경로를 모두 고려해야 최솟값을 구할 수 있습니다.
🔍 다른 사람 답안
n = int(input())
dp = [0] * (n + 1)
for i in range(2, n + 1):
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)
print(dp[n])
$i$가 6으로 나누어떨어지는 경우를 별도로 분리하지 않고 2로 나누어떨어지는 경우와 3으로 나누어떨어지는 경우를 독립적으로 처리합니다. 두 조건이 독립적이므로 $i$가 6으로 나누어떨어지는 경우에도 자연스럽게 $dp[i//2]$와 $dp[i//3]$ 경로를 모두 비교하게 됩니다.
728x90
반응형
'코딩테스트 대비' 카테고리의 다른 글
[파이썬(Python)] 백준 11727번 2×n 타일링 2 (0) | 2024.12.12 |
---|---|
[파이썬(Python)] 백준 11726번 2×n 타일링 (0) | 2024.12.11 |
[파이썬(Python)] 백준 11653번 소인수 분해 (0) | 2024.12.09 |
[파이썬(Python)] 백준 11576번 Base Conversion (1) | 2024.12.06 |
[파이썬(Python)] 백준 17103번 골드바흐 파티션 (0) | 2024.12.05 |