-
[다이나믹 프로그래밍] 문제 이름 : 1로 만들기Algorithm/유형별 문제 풀기 2021. 11. 24. 12:06
문제 설명
정수 X가 주어질 때 정수 X에 사용할 수 있는 연산은 다음과 같이 4가지 이다.
1. X가 5로 나누어떨어지면, 5로 나눔
2. X가 2로 나누어떨어지면, 2로 나눔
3. X가 3으로 나누어떨어지면, 3으로 나눔
4. X에서 1을 뺌
정수 X가 주어졌을 때, 위의 연산 4개를 적절히 사용해 1을 만들려고 한다. 연산을 사용하는 횟수의 최소값을 구하시오.
사용 개념
다이나믹 프로그래밍, 보텀업 방식
문제 해결 아이디어
모든 연산 가능 경우에 대해 생각해봐야 할 것 같은데 너무 많은 것 아니야..? → 맞아! 경우의 수로 모든 경우에 대해 봐야되는거 맞는데 다이나믹 프로그래밍을 사용해서 빠르게 구하는거지! 어차피 최소 연산 횟수 구하는 것이니까!1. 함수 호출 과정 도식화하기
→ 모든 경우의 수에 대해 고려할 때 동일한 함수들이 여러 번 호출됨을 알 수 있음
→ 이때 동일한 함수에서 구하는 값들은 모두 동일해야 하므로 다이나믹 프로그래밍 적용 가능
** 다이나믹 프로그래밍을 사용하기 위한 조건
https://fordevelop.tistory.com/53#다이나믹-프로그래밍을-사용하기-위한-조건
2. 점화식 표현
→ aᵢ : i 값을 1로 만들기 위해 필요한 최소 연산 횟수
3. 점화식을 바탕으로 보텀업(Bottom-Up) 다이나믹 프로그래밍 코드 작성
코드
import java.util.Scanner; public class Main { public static int[] result = new int[30001]; // 배열의 원소 값 : 해당 값을 1로 만들기 위해 필요한 연산 횟수의 최소값, 한 번 계산된 결과를 배열에 저장해둠 public static void main(String[] args) { Scanner kbd = new Scanner(System.in); int val = kbd.nextInt(); // 최대 : 30,000 // 다이나믹 프로그래밍 진행(보텀업) for(int i = 2; i <= val; i++) { // 연산1. 현재의 수 - 1 result[i] = result[i-1] + 1; // 연산2. 현재의 수가 2로 나누어 떨어지는 경우 if (i % 2 == 0) result[i] = Math.min(result[i], result[i/2] + 1); // 연산3. 현재의 수가 3으로 나누어 떨어지는 경우 if (i % 3 == 0) result[i] = Math.min(result[i], result[i/3] + 1); // 연산4. 현재의 수가 5로 나누어 떨어지는 경우 if (i % 5 == 0) result[i] = Math.min(result[i], result[i/5] + 1); } // 연산 하는 횟수의 최솟값 구하기 System.out.println(result[val]); } }
→ 구하는 것 : 사용자가 입력한 값을 1로 만들기 위해 필요한 연산 횟수의 최소값 (= result[x] 값)
→ 배열의 원소 값 : 해당 값을 1로 만들기 위해 필요한 연산 횟수의 최소값
→ 보텀업 방식으로 작은 값부터 차례대로 연산 횟수의 최소값을 구함
'Algorithm > 유형별 문제 풀기' 카테고리의 다른 글
[다이나믹 프로그래밍] 문제 이름 : 바닥 공사 (0) 2021.12.21 [다이나믹 프로그래밍] 문제 이름 : 개미 전사 (0) 2021.12.21 [이진 탐색] 문제 이름 : 떡볶이 떡 만들기 - 파라메트릭 서치 (0) 2021.11.22 [이진 탐색] 문제 이름 : 부품 찾기 - 배열 Sort, Binary Search (0) 2021.11.18 [배열 정렬] 문제 이름 : 두 배열의 원소 교체 (0) 2021.09.30