1 / 35

動態規劃

動態規劃. Dynamic Programming. 精神. 把大問題分解成性質相似的小問題 (Divide and Conquer) 把重複出現的小問題的答案 記錄下來. 費氏數列. int fib( int n) { if(n==0) return 0; if(n==1) return 1; else return fib(n-1) + fib(n-2); }. fib(5). fib(3). fib(4). fib(1). fib(2). fib(2). fib(3). fib(1). fib(0). fib(1). fib(0).

Download Presentation

動態規劃

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 動態規劃 Dynamic Programming

  2. 精神 • 把大問題分解成性質相似的小問題 (Divide and Conquer) • 把重複出現的小問題的答案記錄下來

  3. 費氏數列

  4. int fib(int n) { if(n==0) return 0; if(n==1) return 1; else return fib(n-1) + fib(n-2); }

  5. fib(5) fib(3) fib(4) fib(1) fib(2) fib(2) fib(3) fib(1) fib(0) fib(1) fib(0) fib(1) fib(2) fib(0) fib(1)

  6. intdp[MAX];// initialize with 0 int fib(int n) { if(dp[n]) return dp[n]; if(n==0) return dp[n] = 0; if(n==1) return dp[n] = 1; else return dp[n] = fib(n-1) + fib(n-2); }

  7. fib(5) fib(3) fib(4) fib(1) fib(2) fib(2) fib(3) fib(0) fib(1) 1 1 2 3 5

  8. Top-down • Easy and Clear • Slow fib(5) fib(3) fib(4) fib(1) fib(2) fib(2) fib(3) fib(0) fib(1)

  9. Bottom-up int fib[MAX]; fib[0] = 0; fib[1] = 1; for(inti=2; i<=n; i++) fib[i] = fib[i-1] + fib[i-2];

  10. 演算法設計 • 找出初始值、問題範圍 • 寫出把大問題分解成小問題的遞迴式 • 用陣列把算過的問題答案記錄下來 • 加速:安排計算順序 (小問題→大問題),用迴圈實作

  11. 走樓梯 • 走樓梯,一步可以走一階或兩階 • 樓梯共n階,有幾種不同走法?

  12. Solution • 1階的樓梯有1種走法 • 2階的樓梯有2種走法 (2or 1+1) • 3階的樓梯有3種走法 (1+1+1, 1+2, 2+1) • …

  13. Solution • n階的樓梯: • 第一步走一階→剩下n-1階 • 第一步走兩階→剩下n-2階 • 走n階樓梯的方法數 = 第一步走一階的方法數 + 第一步走兩階的方法數 = 走n-1階的方法數 + 走n-2階的方法數

  14. Solution • 令f(n)為走n階樓梯的方法數 • f(1) = 1 • f(2) = 2 • f(n) = f(n-1) + f(n-2)

  15. Staircase Walk • 一個n*m的棋盤,從左上角走到右下角,一步只能往右走一格或往下走一格,有幾種走法? n = 11, m = 9 (1,1) (n,m)

  16. Solution • 令s(n,m)為從起點(1,1)走到(n,m)的方法數 • n=1 or m=1時只有1種走法(一直往下走 or 一直往右走) → s(1,k)=1, s(k,1)=1 • 走到(n,m)的方法數 = 從上面走來的方法數 + 從左邊走來的方法數 =s(n, m - 1) + s(n - 1, m)

  17. Solution intdp[MAXN][MAXM];// 初始化為0 int s(int n, int m) { if(dp[n][m]) return dp[n][m]; if(n==1 || m==1) return dp[n][m] = 1; return dp[n][m] = s(n, m-1) + s(n-1, m); }

  18. Solution intdp[MAXN][MAXM]; for(inti=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(i==1 || j==1) dp[i][j] = 1; else dp[i][j] = dp[i][j-1] + dp[i-1][j]; } }

  19. 空間優化 intdp[MAXM]; for(inti=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(i==1 || j==1) dp[j] = 1; else dp[j]= dp[j-1] + dp[j]; } }

  20. 切棒子 • 不同長度的鐵棒有不同的價格 • 我有一根鐵棒要賣,可以直接賣掉,也可以切成小段分開出售 • 要怎麼切才有最大獲利?

  21. Solution • 設鐵棒長度n • 先切一段長k下來,賣出價格p[k] • 剩下長度n-k → 求長度n-k的鐵棒可以賣得的最大獲利 • 對每一個k都試試看,取最大值

  22. Solution • 令c(n)為長度n的鐵棒可以賣出的最高價 • c(0) = 0 • c(n) = max(p[k]+c(n-k)) ∀ 1 ≤ k ≤ n

  23. // top-down intdp[MAX]; // init with 0 int c(int n) { if(dp[n]) return dp[n]; if(n==0) return 0; int q = -1; for(int k=1; k<=n; k++) q = max(q, p[k]+c(n-k)); return dp[n] = q; }

  24. // bottom-up intdp[MAX]; dp[0] = 0; for(inti=1; i<=n; i++) { int q = -1; for(int k=1; k<=i; k++) q = max(q, p[k]+dp[i-k]); dp[i] = q; }

  25. Longest Common Subsequence • 子序列 (Subsequence):從一個序列中任選幾個數字所組成 • 15324 → 2、1 3、5 3 4、1 5 3 2 4、Ø • 輸入兩個序列,找出最長的共同子序列長度 s1:15324 1524 s2: 2145024

  26. Solution • 設LCS(a, b)為”序列s1取到第a項,序列s2取到第b項”時,LCS的長度 • 情況1:s1[a] ∈ LCS,s2[b] ∉LCS → LCS=s1[1~a]和s2[1~b-1]的LCS → LCS(a, b) = LCS(a, b-1) • 情況2:s1[a] ∉ LCS,s2[b] ∈ LCS → LCS = s1[1~a-1]和s2[1~b]的LCS → LCS(a, b) = LCS(a-1, b)

  27. Solution • 情況3:s1[a] ∉LCS,s2[b] ∉ LCS → LCS(a, b) = LCS(a-1, b-1) • 情況4:s1[a] ∈ LCS,s2[b] ∈ LCS → s1[a] == s2[b] → LCS(a, b) = LCS(a-1, b-1) + 1

  28. Solution

  29. 0/1背包問題 • 一背包,容量V • k種物品,體積c[1] ~ c[k],價值w[1] ~ w[k] • 每種物品只有一個,可選擇拿或不拿 • 背包最多可以裝多少價值的物品?

  30. Solution • 設kp(k, V)為容量V的背包”取到第k件物品”時,可以達到的最大總價值 • 情況一:取第k件物品 (c[k] ≤ V) → kp(k, V) = kp(k-1, V-c[k]) + w[k] • 情況二:不取第k件物品 → kp(k, V) = kp(k-1, V)

  31. Solution

  32. // bottom-up intkp[MAXK][MAXV]; for(inti=0; i<=k; i++) { for(int v=0; v<=V; v++) { if(i==0){ kp[i][v] = 0; continue; } if(v<c[i]) kp[i][v] = kp[i-1][v]; else kp[i][v] = max(kp[i-1][v], kp[i-1][v-c[i]]+w[i]); } }

  33. 空間優化 intkp[MAXV];//init with 0 for(inti=1; i<=k; i++) for(int v=V; v>=c[i]; v--) kp[v] = max(kp[v], kp[v-c[i]]+w[i]);

  34. 演算法筆記 (http://www.csie.ntnu.edu.tw/~u91029/) • 背包問題九講 (http://crc.hs.ntnu.edu.tw/pack/)

More Related