✏️ 문제 탐색
https://www.acmicpc.net/problem/25418
정수 A에 1을 더한다.
정수 A에 2를 곱한다.
두 연산을 이용하여 A를 K로 변경할 때, 최소 연산 횟수를 구하는 문제이다.
✏️ 구현 아이디어
모든 경우를 완전 탐색으로 찾는 경우 시간 복잡도는 O(2^N)이다.
A와 K가 최대 1,000,000이므로 최대 연산은 2^1,000,000
2^10=약 1,000이므로 2^1,000,000은 제한 시간(1초) 안에 연산할 수 없다.
A가 K가 될 수 있는지 판단하려면 1을 더하고 2를 곱하면서 모든 경우를 찾는 수밖에 없다.
하지만 반대로 K에서 1을 빼고 2를 나누면서 A가 될 수 있는지 판단한다면 불필요한 경로를 배제할 수 있다.
예를 들어 7이 77이 될 수 있는지 판단한다면 7에서 +1, *2 두 가지 연산을 하고
그 결과 각각마다 또 +1, *2 두 가지 연산을 하는 행위를 반복해야 한다.
하지만 반대로 77이 7이 될 수 있는지 판단한다면 77에서 -1, /2 두 가지 연산을 할 것이다.
이 때 77/2는 정수로 떨어지지 않는다. 즉 7에서 77이 되기 위해 이 경로를 거치지 않았다는 의미이다.
따라서 이 탐색경로는 연산에서 배제시킬 수 있다.
✏️ 알고리즘
백트래킹
✏️ 시간 복잡도
현재 탐색 중인 숫자가 홀수일 때마다 탐색 횟수가 반씩 줄어들기 때문에 O(K/2 + logK/2)가 아닐까 예상해봄..
✏️ 오답 노트
백트래킹 조건으로 if(K<A) return;을 빠트림
✏️ 코드 설계
- A, K 입력 받기
- K에서 -1, /2연산을 백트래킹으로 수행
- 이미 K=A인 경우를 찾았거나, K가 A보다 작아진 경우 더 이상 수행할 필요 없으므로 재귀 탐색 종료
- K=A이면 연산을 몇 번 수행했는지 저장하고 탐색 종료
- K값이 0 이하이면 더 이상 수행할 필요 없으므로 탐색 종료
- K가 2의 배수일 때만 2로 나눈 값을 재귀호출
- 그 외의 경우 모두 1 뺀 값을 재귀호출
- A를 가장 먼저 찾는 경우, 백트래킹 종료하고 연산 횟수를 출력
✏️ 정답 코드
import java.io.*;
import java.util.*;
public class Main{
static int A, K, ans, totalcnt;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
//입력 받기
StringTokenizer st = new StringTokenizer(br.readLine());
A = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
recursive(K, 0);
System.out.println(ans);
}
static void recursive(int K, int cnt){
if(ans != 0 || K<A) return;
if(K == A){
ans = cnt;
return;
}
if(K <= 0) return;
if(K%2 != 0) recursive(K-1, cnt+1);
else recursive(K/2, cnt+1);
recursive(K-1, cnt+1);
}
}
✏️ Note
- 사실 이 풀이 방법이 맞는지 긴가민가했다. 시간 복잡도를 정확하게 계산하지 못한 상태에서 풀었기 때문에..
- 비슷한 문제를 예전에도 풀어본 적이 있어서 백트래킹을 떠올릴 수 있었다.
- 조건을 빠트려서 중간에 시간 초과가 한 번 나긴 했지만 유형과 풀이 방법을 빨리 떠올릴 수 있었던 문제이다.
'코테' 카테고리의 다른 글
| [백준/Java] 25644번 : 경비원 (0) | 2025.01.24 |
|---|---|
| [백준/Java] 13702번 : 이상한 술집 (0) | 2025.01.23 |
| [백준/Java] 2467번 : 용액 (2) | 2025.01.21 |
| [백준/Java] 2805번 : 나무 자르기 (1) | 2025.01.20 |
| [백준/Java] 11663번 : 선분 위의 점 (1) | 2025.01.19 |