動態規劃-隔鋼條-演算法導論-2021/1/1
動態規劃-割鋼條
下面給出一個簡單的題目,分析過程我借鑑的是演算法導論那本書的例子。順便給自己做一個筆記。
然後體驗一下人家的分析過程,並且把過程抽象化,對演算法的設計有多大作用。
第一:看了題目之後,我們首先想到的是先切割,然後再對應表格計算價錢。
比如長度L=4時,如上圖對應的有八種切割方式。當切割為兩段時,出售的價錢是最高 = 10。當L=1時,是不切,價錢為1。L=2時也是不切,價錢為5。當L = 3時有四種切割方案不切的時候價錢才是最高的。
總結上面的,我可以得出,每一段鋼條都有其對應的最優解。所以我們設,L = n時,切成k段時有最優解
最優切段:L{n} = i1 + i2 + … + ik(1 <= k <= n) —> i1…代表切斷的長度
最優價格:R{n} = P{i1} + P{i2} + … + P{ik}(1 <= k <= n)
上面兩個公式時對每一段鋼條的最優切割進行抽象,對應的就是最優價錢。我們知道,每一段鋼條切割之後,會變成兩段,然後再求兩個段的最優解。就比如L = 4,分為兩段的時候是L = 2 + 2,2本身就是最優解,所以L = 4時,P = 10。
所以當我們求n段的最優解時,有P{n} = max(R{n},R{i1}+R{n-i1},…,R{n-i1}+R{i1}),這公式的意思是,從所有的切斷中求最優解。
自頂向下的概念,這個的意思是,要求子問題x的時候、得呼叫自身(遞迴)把x裡面的子問題再進行求
解,把x所有的子問題求解完畢,才得到x本身。比如:再上面的圖中,要對L = 4進行求解的時候,切
為兩段時有1,3兩中長度,這個時候得對3求最優解才能得到從第一個位置切i=1時的最優解。
自頂向下的遞迴—虛擬碼
CUT-ROD(p,n)
— if(n == 0) return 0
— q = Integer.MIN_VALUE
------- for i = 1 to n
----------- //這個動態轉移方程就是上面公式P{n},可以好好體會一下
----------- q = max(p[i]+CUT-ROD(p,n-i),p)
— return q
上面虛擬碼的p代表的是價格表,n代表的是鋼條一共多長
自頂向下帶備忘錄的遞迴—虛擬碼
CUT-ROD(p,r,n)
— if(r[n]>0) return r[n]
— if(n==0) return 0
— for i = 0 to p.length
------ r[i] = p[i]//初始化
— q = Integer.MIN_VALUE
------ for i = 1 to n
--------- q = max(r[i] + CUT-ROD(p,r,n-i),q)
------ r[i] = q//記錄最優解
— return r[n]
上面是帶備忘錄的自頂向下的動態規劃
自底向上:再對x子問題進行求解的時候,先把它用到的子問題進行求解。這個跟自頂向上沒有本質的
區別,主要的區別在於求解問題規模的順序。
虛擬碼:
CUT-ROD(p,n)
— if(r[n]>0) return r[n]
— if(n==0) return 0
— for i = 0 to p.length
------ r[i] = p[i]//初始化
— q = Integer.MIN_VALUE
------ for i = 1 to n
--------- for j = 1 to i
------------ q = max(r[i]+r[i-j],q)
------ r[i] = q//記錄最優解
— return r[n]
在這裡插入程式碼片
//至頂向下--遞迴
public int cutrod(int[] priceTbale,int n) {
if (n == 0) return 0;
int price = Integer.MIN_VALUE;
for (int i = 1; i <= n; i++) {
price = Math.max(priceTbale[i]+cutrod(priceTbale, n-i), price);
}
return price;
}
//自頂向下--備忘遞迴
public int memoizedCutRodAux(int dp[],int n) {
if (n == 0) return 0;
if (n > 10 && dp[11] > 10) {
return dp[n];
}
int value = Integer.MIN_VALUE;
for (int i =1; i <= n; i++) {
value = Math.max(dp[i]+memoizedCutRodAux(dp,n-i),value);
}
dp[n] = value;
return value;
}
public int memoizedCutRod(int price[],int n) {
int dp[] = new int[n+1];
for (int i = 1; i < price.length; i++) {
dp[i] = price[i];
}
return memoizedCutRodAux(dp,n);
}
//自底向上
public int bottomUpCutRod(int price[],int n) {
int r[] = new int[n+1];
r[0] = 0;
for (int i = 1; i < price.length; i++) {
r[i] = price[i];
}
for (int i = 1; i <= n; i++) {
int q = Integer.MIN_VALUE;
for (int j = 1; j <= i; j++) {
q = Math.max(q, r[j]+r[i-j]);
}
r[i] = q;
}
return r[n];
}
相關文章
- 演算法系列-動態規劃(1):初識動態規劃演算法動態規劃
- 動態規劃演算法(DP)學習<1>動態規劃演算法
- 動態規劃方法論動態規劃
- Day32 動態規劃Part1動態規劃
- 動態規劃之理論分析動態規劃
- 演算法-動態規劃演算法動態規劃
- 演算法_動態規劃演算法動態規劃
- 動態規劃演算法動態規劃演算法
- 0-1揹包問題(動態規劃)動態規劃
- 前端演算法 - 動態規劃前端演算法動態規劃
- 動態規劃之0,1揹包問題動態規劃
- 動態規劃解0-1揹包問題動態規劃
- 初級演算法-動態規劃演算法動態規劃
- 【每日演算法】動態規劃四演算法動態規劃
- 前端學習演算法1 :老虎和羊,吃不吃問題(動態規劃入門)前端演算法動態規劃
- 動態規劃之 0-1 揹包問題詳解動態規劃
- 演算法(七):圖解動態規劃演算法圖解動態規劃
- 演算法-動態規劃-完全揹包演算法動態規劃
- 動態規劃動態規劃
- 演算法---貪心演算法和動態規劃演算法動態規劃
- 【動態規劃】0-1揹包問題原理和實現動態規劃
- 演算法筆記之動態規劃(4)演算法筆記動態規劃
- Leetcode 題解演算法之動態規劃LeetCode演算法動態規劃
- 矩陣連乘(動態規劃演算法)矩陣動態規劃演算法
- 動態規劃之 KMP 演算法詳解動態規劃KMP演算法
- 動態規劃演算法原理與實踐動態規劃演算法
- 理論+實踐,帶你掌握動態規劃法動態規劃
- [leetcode] 動態規劃(Ⅰ)LeetCode動態規劃
- 動態規劃法動態規劃
- 模板 - 動態規劃動態規劃
- 動態規劃初步動態規劃
- 動態規劃分析動態規劃
- 動態規劃(DP)動態規劃
- 洛谷題單指南-動態規劃1-P1164 小A點菜動態規劃
- [leetcode初級演算法]動態規劃總結LeetCode演算法動態規劃
- 演算法基礎--遞迴和動態規劃演算法遞迴動態規劃
- 乾貨:圖解演算法——動態規劃系列圖解演算法動態規劃
- 動態規劃演算法——裝最多水的容器動態規劃演算法