지난 학기 학교 알고리즘 수업을 수강하며, 정리 해 놓았던 마크다운 문서입니다. 문제시 삭제하겠습니다
fibDPwrap(n)
Dict soln = create(n); // 사이즈 n 테이블 생성
return fibDP(soln,n);
fibDP(soln,k)
int fib, f1, f2;
if (k < 2) fib = k; // base case
else if (member(soln,k-1) == false) //soln 에 sol저장 안되있으면
f1 = fibDP(soln,k-1); //재귀 통해 k-1 다시 실행
else f1 = retrieve(soln,k-1); // 계산 되있으면 단순히 테이블에서 읽어오기
if (member(soln,k-2) == false) f2 = fibDP(soln,k-2);
else f2 = retrieve(soln,k-2);
fib = f1 + f2;
store(soln,k,fib);
return fib;
// bottom up은?
F0=0;
F1=1;
for i=2 to n
Fi=Fi-1+Fi-2;
입력 : n개의 행렬 주어짐
결합 법칙 성립
어떤 순서로 곱하던 결과 값 같음, 곱셈 연산순서가 가장 적은 경우가 언제인지 찾는 문제
matrix Ai의 차원 pi-1 * pi 로 정의
두개의 행렬 곱할때 연산의 수 살펴보기 (p x q, q x r)
top-down 대신 bottom-up 이용 계산
Ex) A1 = 30 × 1, A2 = 1 × 40, A3 = 40 × 10, A4 = 10 × 25
𝒑𝟎 = 𝟑𝟎, 𝒑𝟏 =1, 𝒑𝟐 = 𝟒𝟎, 𝒑𝟑 = 𝟏𝟎, 𝒑𝟒 =25.
m, s table 계산 완료, 최종적으로 마지막 값 1400이 optimal solution의 value (A1부터 A4까지 필요한 곱셈연산의 최소 횟수)
PRINT-OPTIMAL-PARENS(𝑠, 𝑖,𝑗) //i=1, j=4
1 if 𝑖 = 𝑗
2 then print “A”i //base case
3 else print “(”
4 PRINT-OPTIMAL-PARENS(𝑠, 𝑖, 𝑠[𝑖,𝑗]) //s[i,j]에는 k값 저장 (Ai..Ak) -> left child
5 PRINT-OPTIMAL-PARENS(𝑠, 𝑠[𝑖,𝑗]+1, 𝑗) //s[i,j]+1=k+1 (Ak+1...Aj) -> right child
6 print “)
recursion tree로 표현 가능
초기값 s[1,4]에 대한 k 값=1
(1,4)의 left child는 i,k로 나타낼수 있으므로 (1, 1)
right child는 k+1, j 로 나타낼수 있으므로 (2,4)
위와 같은 방식으로 트리 만들 수 있음
왼쪽 자식 호출되기전 "(" 출력
오른쪽 자식이 호출되고 난후 직후 돌아올때 ")" 출력
in order 순회 방식으로 출력
-> (A1((A2A3)A4)) 곱셈 순서 출력 가능!!
Step 3 : matrix chain 길이 1 일때 계산, 2일때 계산, 3일때 계산,,,, n일때까지 계산 -> n+(n-1)+...+1 = O(n^2)의 셀 존재
하나의 셀 계산하는데 o(n) time 걸림
따라서 O(n^3) time, O(n^2) space
Step 4 : recursion tree노드 개수 분석
n개의 leaf 존재, n-1개의 internal node가짐 -> 총 2n-1개의 노드 가짐 따라서 O(n) time 에 수행가능
O(n^2) space (s 테이블을 계속 사용하기 때문)