题目描述
已知一个背包最多能容纳物体的体积为V
现有n个物品第i个物品的体积为vi,第i个物品的重量为wi。求当前背包最多能装多大重量的物品
方法一:动态规划
求解思路
对于求解01背包问题,我们想到使用动态规划进行求解,可以发现,对于一个物体,我们有两种选择,放或者不放进背包。这样便将问题划分成了更小的子问题。我们使用表示当前第i个物品,背包体积为V时能够得到的最大重量和。表示题目所给的物体的体积和重量。因此根据第i-1个物品的放或者不放进背包的情况对第i个物品进行讨论,我们即可得到转移方程为:,最终我们得出题目要求的答案。
解题代码
class Solution { public: int knapsack(int V, int n, vector<vector<int> >& vw) { vector<vector<int>> hydp(n + 1, vector<int>(V + 1)); for(int i = 1; i <= n; ++i) { for(int j = 1; j <= V; ++j) { hydp[i][j] = hydp[i - 1][j]; // 不装入物品 if(j >= vw[i - 1][0]) { //体积足够,可以装入 hydp[i][j] = max(hydp[i][j], hydp[i-1][j-vw[i-1][0]]+vw[i-1][1]); } } } return hydp[n][V]; // 返回结果 } };
复杂度分析
时间复杂度:使用了两层循环,因此时间复杂度为 ,其中n为物体的个数,v为物体的体积。
空间复杂度:引入dp[n][v]数组,因此空间复杂度为 ,其中n为物体的个数,v为物体的体积。
方法二:优化方法--动态优化
求解思路
对于动态规划我们对其进行优化,根据方法一的代码,我们发现每次对于i的选择都只与第i-1层相关,所以我们使用滚动数组对本题进行空间角度的优化。
解题代码
class Solution { public: int knapsack(int V, int n, vector<vector<int> >& vw) { vector<int> hydp(V + 1); // 声明辅助数组 for(int i = 1; i <= n; ++i) { for(int j = V; j > 0; --j) // 这里使用辅助数组,在空间角度对其优化 { if(j >= vw[i - 1][0]) { //体积足够,可以装入 hydp[j] = max(hydp[j], hydp[j - vw[i - 1][0]] + vw[i - 1][1]); } // 不能装入时数组大小保持原样即可 } } return hydp[V]; // 返回结果即可 } };
复杂度分析
时间复杂度:两层循环,因此时间复杂度为 ,其中n为物体的个数,v为物体的体积。
空间复杂度:引入dp[n]数组,因此空间复杂度为