動態規劃(dynamic programming)
什麼是動態規劃,我們要如何描述它?
動態規劃演算法通常基於乙個遞推公式及乙個或多個初始狀態。當前子問題的解將由上一次子問題的解推出。
動態規劃和分治法相似,都是通過組合子問題的解來求解原問題。分治法將問題劃分成互不相交的子問題,遞迴求解子問題,再將他們的解組合起來,求出原問題的解。與之相反,動態規劃應用於子問題重疊的情況,即不同的子問題具有公共的子子問題。在這種情況下,分治演算法會做出許多不必要的工作,它會反覆的求解那些公共子問題。而動態規劃演算法對每個子子問題只求解一次,將結果儲存到**中,從而無需每次求解乙個子子問題都要重新計算。
鋼條切割利潤最大化問題描述:
給出下面乙個鋼條的長度(int型別)和對應的**表,求出給定長度n公尺(int型別)的鋼條如何切割才能獲得最大收益。
長度(m)12
**實現:
using system;
namespace _4_1_1動態規劃_鋼條切割_遞迴
; * 給定一長度為n的鋼條和一張**表(i =1, 2,3...n),求切割鋼條的方案,
* 使的利潤最大,可以不進行切割
*/class program
;console.writeline(updown(1, p));
console.writeline(updown(2, p));
console.writeline(updown(3, p));
console.writeline(updown(4, p));
console.writeline(updown(5, p));
console.writeline(updown(6, p));
console.writeline(updown(7, p));
console.writeline(updown(8, p));
console.writeline(updown(9, p));
console.readkey();
}///
/// 鋼條切割遞迴演算法
//////
要切割的長度
///索引**鋼條的長度,值代表**
///public
static
intupdown(int n,int p)
}return maxprice;} }
}
執行結果:
遞迴優化:
優化思路也和簡單:當我們使用遞迴解決問題的時候,會發現相同的問題會執行多次,比如我們求長度為5的最大利潤的時候,就會把長度為4 的最大利潤也求出來,而求長度為6的最大利潤時,還需要把長度為5,長度為4的最大利潤在求一次,,,如果可以長度為n的最大利潤可以儲存下來,那麼程式執行起來就會快很多了,,,優化**如下:
namespace _4_1_2動態規劃_鋼條切割_遞迴優化
; //用於儲存所求長度的最大利潤,
int result = new
int[p.length+1];
console.writeline(updown(1, p,result));
console.writeline(updown(2, p,result));
console.writeline(updown(3, p,result));
console.writeline(updown(4, p,result));
console.writeline(updown(5, p,result));
console.writeline(updown(6, p,result));
console.writeline(updown(7, p,result));
console.writeline(updown(8, p,result));
console.writeline(updown(9, p,result));
console.readkey();
}///
/// 鋼條切割遞迴演算法
//////
要切割的長度
///索引**鋼條的長度,值代表**
///public
static
intupdown(int n, int p,int result)
}result[n] = maxprice;
return maxprice;}}
}
動態規劃的方法進行求解上面的方法之所以效率很低,是因為它反覆求解相同的子問題。因此,動態規劃演算法安排求解的順序,對每個子問題只求解一次,並將結果儲存下來。如果隨後再次需要此子問題的解,只需查詢儲存的結果,不必重新計算。因此動態規劃的方法是付出額外的記憶體空間來節省計算時間。
自底向上法
首先恰當的定義子問題的規模,使得任何問題的求解都只依賴於更小的子問題的解。因而我們將子問題按照規模排序,按從小到大的順序求解。當求解某個問題的時候,它所依賴的更小的子問題都已經求解完畢,結果已經儲存。
**實現:
using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
namespace _4_1_3動態規劃_鋼條切割_自底向上
; //用於儲存所求長度的最大利潤,
int result = new
int[p.length + 1];
console.writeline(bottomup(1, p, result));
console.writeline(bottomup(2, p, result));
console.writeline(bottomup(3, p, result));
console.writeline(bottomup(4, p, result));
console.writeline(bottomup(5, p, result));
console.writeline(bottomup(6, p, result));
console.writeline(bottomup(7, p, result));
console.writeline(bottomup(8, p, result));
console.writeline(bottomup(9, p, result));
console.readkey();
}public
static
intbottomup(int n,int p,int result)
}result[i] = maxprice;
}return result[n];}}
}
動態規劃 鋼條切割
一家公司購買長鋼條,將其切割成短鋼條 切割本身沒有成本,長度為i的短鋼條的 為pi。那給定一段長度為n的鋼條和乙個 表pi,求鋼條的切割方案使得收益rn最大。如乙個pi如下 長度i12 3456 78910 pi15 891017 1720 2430 在距離鋼條左端i長度處,我們總是可以選擇切割或者...
動態規劃 鋼條切割
這是演算法導論動態規劃的乙個例子,自己實現了一下 給定乙個長度為n英吋的鋼條和乙個 表pi i 1,2 n 求切割鋼條方案,使得銷售收益rn最大。注意,如果長度為n的鋼條 pn足夠大,則最優解可能就不需要切割。分析 如下 include include include using namespace...
動態規劃 切割鋼條
動態規劃按照我的理解就是避免重複計算,犧牲空間換時間,將重複計算的結果儲存起來,下次用的時候,直接使用儲存的結果,我文字不多,直接上 沒有程式設計基礎的兄弟們可能不太能看懂 兩種方式一種是遞迴,另一種是遞推 其實就是採用for迴圈 動態規劃 切割鋼條 公尺 m 1 2 3 4 5 6 7 8 9 1...