다이나믹 프로그래밍
메모리공간을 사용하여 연산속도를 비약적으로 증가시킬 수 있는 방법
다이나믹 프로그래밍을 이용하여 해결할 수 있는 대표적 예시
피보나치 수열(그냥 재귀함수로 풀 수 있으나 시간이 매우 많이 듦 > 때문에 이 기법 사용)
만약 완전탐색 알고리즘으로 풀었을때 너무 오래걸리고, 해결하고자 하는 문제에 중복부분이 있다면 다이나믹 프로그램을 사용하는 것을 생각해볼 수 있음
사용하기 위한 전제조건
큰 문제를 작은 문제로 나눌 수 있다.
작은 문제에서 구한 정답은 그것을 포함하는 큰 문제에서도 동일하다.
탑다운/보텀업 방식
- 탑다운 방식: 재귀함수를 이용한 방법으로 큰 문제를 해결하기 위해 작은 문제를 호출
- 보텀업 방식: 단순히 반복문을 이용하여 소스코드를 작성하는 경우로 작은문제부터 차근차근 답을 도출
보텀업이 다이나믹 프로그래밍의 전형적인 형태
다이나믹 프로그래밍 구현 방법
메모이제이션(=캐싱) : 한번 구한 결과를 메모리공간에 보관하고 같은 식을 호출 시 이 결과를 가져옴
재귀함수로 하면 오버헤드가 발생할 수 있다.
시간복잡도 O(N)
일반적으로 반복문을 이용한 다이나믹 프로그래밍이 더 성능이 좋다.
let arr = []; //보관용 arr
function fibo(x) {
if ((x == 1 ) || ( x == 2)) return 1
if (arr[x] != undefined ) return arr[x] //기존에 작업했으면 그걸 호출
else {
arr[x] = fibo(x-1)+fibo(x-2) ;
return arr[x]; //보관
}
}
console.log(fibo(8)) ; //8번째 수가 무엇인가 반환
[예제문제] 1로 만들기
- X가 5로 나누어떨어지면, 5로 나눈다.
- X가 3으로 나누어떨어지면, 3으로 나눈다.
- X가 2로 나누어떨어지면, 2로 나눈다.
- X에서 1을 뺀다.
정수 X가 주어졌을 때, 연산 4개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.
정수 X가 주어질 때 정수 X에 사용할 수 있는 연산은 다음과 같이 4가지이다.
let input = require('fs').readFileSync('input.txt').toString().trim() ;
let x = +input ;
let cache = {}
let ret ;
function M(x){
if (cache.hasOwnProperty('x')) {
return cache.get(x) ;
}
if (x == 1 ) return 0
ret = M(x-1)
if (x % 5 == 0) {
ret = Math.min(ret, M(x / 5))
}
if (x % 3 == 0) {
ret = Math.min(ret, M(x / 3))
}
if (x % 2 == 0) {
ret = Math.min(ret, M(x / 2))
}
cache[x] = ret + 1
return cache[x]
}
console.log(M(x));
[예제문제] 개미전사
개미 전사가 정찰병에게 들키지 않고 식량창고를 약탈하기 위해서는 최소한 한 칸 이상 떨어진 식량창고를 약탈해야 한다. 개미 전사를 위해 식량창고 N개에 대한 정보가 주어졌을 때 얻을 수 있는 식량의 최댓값을 구하는 프로그램을 작성하시오.
let input = require('fs').readFileSync('input.txt').toString().trim().split(" ").map(Number) ;
let ret = [input[0], input[1]];
for (let i = 1 ; i < input.length ; i++) {
if ( i == 1 ) ret[1] = Math.max(input[0],input[1]) ;
else {
ret[i] = Math.max(ret[i-2]+input[i],ret[i-1]) ;
}
}
console.log(ret[ret.length-1]);
[예제문제] 바닥공사
가로의 길이가 N, 세로의 길이가 2인 직사각형 형태의 얇은 바닥이 있다. 태일이는 이 얇은 바닥을 1 x 2의 덮개, 2 x 1의 덮개, 2 x 2의 덮개를 이용해 채우고자 한다.
let input = require('fs').readFileSync('input.txt').toString().trim() ;
input = +input ;
let arr = [1, 3]
for (let i = 2 ; i < input ; i++) {
arr[i] = arr[i-2]*2 + arr[i-1]
}
console.log(arr[arr.length-1]%796796) ;
'책 공부' 카테고리의 다른 글
[모던자바스크립트] Number/Math 메서드 정리 (0) | 2023.03.05 |
---|---|
[이것이 코딩테스트다] 7. 이진 탐색 (0) | 2022.11.10 |
[이것이 코딩테스트다] 6. 정렬 (1) | 2022.11.10 |
[이것이 코딩테스트다] 5. DFS/BFS (0) | 2022.11.10 |
[이것이 코딩테스트다] 4. 구현 (0) | 2022.11.10 |