--- tags: Algorithm --- <style> font { color: red; } </style> # Ch03 - Dynamic Programming ## Dynamic Programming v.s. Divide and Conquer ### Differences - **Divide-and-Conquer** - **Top-Down** - Blindly solves the divided instances by using recursion. - Inefficient when the divided instances are related. - Inefficient when the divided instances are almost as large as the original instance. - **Dynamic Programming** - **Bottom-Up** (solve small instances first, **store the results**, and later, whenever we need a result, look it up instead of re-computing it.) - Programming (the use of an array in which a solution is constructed.) ## nth Fibonacci Term (Iterative) Determine the nth term in the Fibonacci sequence. > **Input:** a nonnegative integer `n`. > **Output:** `fib2`, the nth term in the Fibonacci sequence. ```pseudo= int fib2 (int n) { index i; int f[0..n]; f[0] = 0; if (n > 0) { f[1] = 1; for (i=2; i<=n; i++) { f[i] = f[i-1] + f[i-2]; } } return f[n]; } ``` **Time Complexity:** $T(n) = n + 1$ ## Binomial Coefficient Using DP Compute the binomial coefficient. > **Input:** nonnegative integers `n` and `k`, where $k \le n$ > **Output:** `bin2`, the binomial coefficient $(^{n}_{k})$. ```pseudo= int bin2 (int n, int k) { index i, j; int B[0..n][0..k]; for (i=0; i<=n; i++) { for (j=0; j<=minimum(i, k); j++) { if (j == 0 || i == 0) B[i][j] = 1; else B[i][j] = B[i-1][j-1] + B[i-1][j]; } } return B[n][k]; } ``` > Review: [巴斯卡三角形](https://zh.wikipedia.org/zh-tw/%E6%9D%A8%E8%BE%89%E4%B8%89%E8%A7%92%E5%BD%A2) ## Floyd’s Algorithm for Shortest Paths [最短路徑 演算法](https://ithelp.ithome.com.tw/articles/10209186) - **Simple path**: a path that never passes through the same vertice twice. - **Shortest Path Problem** - **Example**: - Air travelers want to determine the shortest way to fly from one city to another when a direct flight does not exist. ```pseudo= void floyd (int n, const number W[][], number D[][]) { index i, j, k; D = W; for (k=1; k<=n; k++) { for (i=1; i<=n; i++) { for (j=1; j<=n; j++) { D[i][j] = minimun(D[i][j], D[i][k] + D[k][j]); } } } } ``` ## Chained Matrix Multiplication - 矩陣乘法的運算效率 - 當 $A \in M_{w \times x}, B \in M_{x \times y}$ - $A \times B$ 需要 $w \times x \times y$ 次乘法運算 <br> - **Chained Matrix Multiplication** - 多個矩陣相乘的運算 - 當矩陣排列順序相同時,相乘的先後順序不影響乘積 $$ ABC = (AB)C = A(BC) $$ - 但是相乘的先後順序會影響運算的效率 $$ \text{For } A \in M_{1 \times 2},\ B \in M_{2 \times 3},\ C \in M_{3 \times 4} \\ (AB) \in M_{1 \times 3},\ (BC) \in M_{2 \times 4}\\\ \\ \begin{split} (AB)&:\ \ 1 \times 2 \times 3 &=\ 6 &\text{ multiplication} \\ (AB)C&: 6 + 1 \times 3 \times 4 &= 18 &\text{ multiplication} \end{split}\\\ \\ \begin{split} (BC)&:\ \ 2 \times 3 \times 4 &= 24 &\text{ multiplication} \\ A(BC)&: 24 + 1 \times 2 \times 4 &= 32 &\text{ multiplication} \end{split}\\ $$ - **Minimum Multiplication** - 尋找 Chained Matrix Multiplication 的 **最小運算次數** 的演算法 - 只找出 **怎麼算** 會最快,但是不會計算出相乘的結果 ### Algorithm - $A_i = d_{i-1} \times d_i$ - $M[i][j] =$ minimum number of multiplications meeded to multiple $A_i$ through $A_j$, if $i<j$ - $P[i][j] =$ the value of $k$ gave $M[i][j]$ $$ M[i][j] = \min_{i \le k \le k}(M[i][k]+M[k+1][j]+d_{i-1}d_kd_j) $$ ![](https://i.imgur.com/OhFQOk7.png) ```cpp int minmult (int n, const int d[], index P[][]) { index i, j, k, diagonal; int M[1..n][1..n]; for (i=1; i<=n; i++) M[i][i] = 0; for (diagonal = 1; diagonal <= n - 1; diagonal++) for (i = 1; i <= n - diagonal; i++) { j = i + diagonal; M[i][j] = min(M[i][k] + M[k+1][j] + d[i-1] * d[k] * d[j]); P[i][j] = k; } return M[1][n]; } ``` ## Optimal Binary Search Tree (OBST) The keys in a binary search tree are organized so that the average time it takes to locate a key is minimized. :::success **Definition:** 不同的插入順序會建構出不同的 BST,而在這些 BST 中,搜尋 node 花費的平均時間最短的就稱為 Optimal Binary Search Tree。 :::