动态规划 —— 01背包问题
生活随笔
收集整理的這篇文章主要介紹了
动态规划 —— 01背包问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
01背包問題
有n個重量和價值分別為wi,vi的物品。
從這些物品中挑選出總重量不超過W的物品,
求所有挑選方案中價值總和的最大值。
針對每個物品是否放入背包進行搜索
#include <iostream>#define MAX_N 100using namespace std;int n, W; int w[MAX_N], v[MAX_N];int rec(int i, int j) { //從第i個物品開始挑選總重量小于j的部分int res;if (i == n) res = 0; //已經沒有剩余物品了else if (j < w[i]) res = rec(i + 1, j); //無法挑選這個物品else res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]); //挑選和不挑選的兩種情況都嘗試一下return res; }int main() {cin >> n;for (int i = 0; i < n; i++)cin >> w[i] >> v[i];cin >> W;cout << rec(0, W) << endl;return 0;這種方法的搜索深度是n,而且每一層的搜索都需要兩次分支,最壞就需要O(2n)的時間,當n比較大的時候就沒辦法解了。
為了避免產生重復計算采用記憶化搜索
#include <iostream> #include <cstring>#define MAX_N 100 #define MAX_W 100using namespace std;int n, W; int w[MAX_N], v[MAX_N]; int dp[MAX_N + 1][MAX_W + 1];int rec(int i, int j) {if (dp[i][j]) return dp[i][j]; //已經計算過的話直接使用之前的結果int res;if (i == n) res = 0;else if (j < w[i]) res = rec(i + 1, j);else res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);return dp[i][j] = res; }int main() {cin >> n;for (int i = 0; i < n; i++)cin >> w[i] >> v[i];cin >> W;memset(dp, 0, sizeof(dp));cout << rec(0, W);return 0; }對于同樣的參數,只會在被調用到時執行遞歸部分,第二次之后都會直接返回。參數的組合不過nW種,而函數內只調用2次遞歸,所以只需要O(nW)的復雜度就能解決。
DP數組
記dp[i][j]根據rec的定義,從第i個物品開始挑選總重小于j時總價值的最大值。
遞推公式:
dp[n][j]=0
if(j<w[i]) dp[i][j]=dp[i+1][j]
else dp[i][j]=max(rec(i+1,j),rec(i+1,j-w[i])+v[i])
總結
以上是生活随笔為你收集整理的动态规划 —— 01背包问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2016年第七届蓝桥杯C/C++ C组国
- 下一篇: 2017年第八届蓝桥杯 - 国赛 - C