自顶向下 与自底向上解决01 背包问题
生活随笔
收集整理的這篇文章主要介紹了
自顶向下 与自底向上解决01 背包问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
01背包問題具體例子:假設現有容量10kg的背包,另外有3個物品,分別為a1,a2,a3。物品a1重量為3kg,價值為4;物品a2重量為4kg,價值為5;物品a3重量為5kg,價值為6。將哪些物品放入背包可使得背包中的總價值最大?
這個問題有兩種解法,動態規劃和貪婪算法。本文僅涉及動態規劃。
先不套用動態規劃的具體定義,試著想,碰見這種題目,怎么解決?
首先想到的,一般是窮舉法,一個一個地試,對于數目小的例子適用,如果容量增大,物品增多,這種方法就無用武之地了。
其次,可以先把價值最大的物體放入,這已經是貪婪算法的雛形了。如果不添加某些特定條件,結果未必可行。
最后,就是動態規劃的思路了。先將原始問題一般化,欲求背包能夠獲得的總價值,即欲求前i個物體放入容量為m(kg)背包的最大價值c[i][m]——使用一個數組來存儲最大價值,當m取10,i取3時,即原始問題了。而前i個物體放入容量為m(kg)的背包,又可以轉化成前(i-1)個物體放入背包的問題。下面使用數學表達式描述它們兩者之間的具體關系。
表達式中各個符號的具體含義。
w[i] : ?第i個物體的重量;
p[i] : 第i個物體的價值;
c[i][m] : 前i個物體放入容量為m的背包的最大價值;
c[i-1][m] : 前i-1個物體放入容量為m的背包的最大價值;
c[i-1][m-w[i]] : 前i-1個物體放入容量為m-w[i]的背包的最大價值;
由此可得:
c[i][m]=max{c[i-1][m-w[i]]+pi , c[i-1][m]}(下圖將給出更具體的解釋)
?
?
根據上式,對物體個數及背包重量進行遞推,列出一個表格(見下表),表格來自(http://blog.csdn.net/fg2006/article/details/6766384?reload) ,當逐步推出表中每個值的大小,那個最大價值就求出來了。推導過程中,注意一點,最好逐行而非逐列開始推導,先從編號為1的那一行,推出所有c[1][m]的值,再推編號為2的那行c[2][m]的大小。這樣便于理解。
這個問題有兩種解法,動態規劃和貪婪算法。本文僅涉及動態規劃。
先不套用動態規劃的具體定義,試著想,碰見這種題目,怎么解決?
首先想到的,一般是窮舉法,一個一個地試,對于數目小的例子適用,如果容量增大,物品增多,這種方法就無用武之地了。
其次,可以先把價值最大的物體放入,這已經是貪婪算法的雛形了。如果不添加某些特定條件,結果未必可行。
最后,就是動態規劃的思路了。先將原始問題一般化,欲求背包能夠獲得的總價值,即欲求前i個物體放入容量為m(kg)背包的最大價值c[i][m]——使用一個數組來存儲最大價值,當m取10,i取3時,即原始問題了。而前i個物體放入容量為m(kg)的背包,又可以轉化成前(i-1)個物體放入背包的問題。下面使用數學表達式描述它們兩者之間的具體關系。
表達式中各個符號的具體含義。
w[i] : ?第i個物體的重量;
p[i] : 第i個物體的價值;
c[i][m] : 前i個物體放入容量為m的背包的最大價值;
c[i-1][m] : 前i-1個物體放入容量為m的背包的最大價值;
c[i-1][m-w[i]] : 前i-1個物體放入容量為m-w[i]的背包的最大價值;
由此可得:
c[i][m]=max{c[i-1][m-w[i]]+pi , c[i-1][m]}(下圖將給出更具體的解釋)
?
?
根據上式,對物體個數及背包重量進行遞推,列出一個表格(見下表),表格來自(http://blog.csdn.net/fg2006/article/details/6766384?reload) ,當逐步推出表中每個值的大小,那個最大價值就求出來了。推導過程中,注意一點,最好逐行而非逐列開始推導,先從編號為1的那一行,推出所有c[1][m]的值,再推編號為2的那行c[2][m]的大小。這樣便于理解。
思路厘清后,開始編程序,C語言代碼如下所示。
自頂向下
#include <stdio.h> #include <tchar.h> #include <queue> #include "iostream" using namespace std; const int N = 4; const int W = 5; int weight[N] = {2, 1, 3, 2}; int value[N] = {3, 2, 4, 2}; int record[N][W]; void init() { for(int i = 0; i < N; i ++) { for(int j = 0; j < W; j ++) { record[i][j] = -1; } } } int solve(int i, int residue) { if(-1 != record[i][residue]) return record[i][residue]; int result = 0; if(i >= N) return result; if(weight[i] > residue) { record[i + 1][residue] = solve(i+1, residue); } else { result = max(solve(i+1, residue), solve(i+1, residue-weight[i]) + value[i]); } return record[i + 1][residue] = result; } int main() { init(); int result = solve(0, W); cout << result << endl; return 0; }總結
以上是生活随笔為你收集整理的自顶向下 与自底向上解决01 背包问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动态规划的用法——01背包问题
- 下一篇: 二叉树 前序、中序、后序、层次遍历及非递