问题:假设有一个容量为C的背包和n中不同的物品,每件物品重量为w(i)、价值v(i);现要在不超过背包容量的基础上,使得物品的总价值最大。
==状态F(n,C):==考虑将n个物品放进容量为C的背包,使得价值最大。
对第i件物品:
***F(i,c) = max( F(i-1, c), v(i) + F(i-1, c-w[i]) )***
本例中w = {1, 2, 3},对应v = {6, 10, 12}。
记忆化搜索
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
class Solution{
public:
int knapsack01(const vector<int>& w, const vector<int>& v, int C){
assert( w.size() == v.size() );
int n = w.size();
if(n == 0)
return 0;
memo = vector<vector<int>>(n, vector<int>(C+1, -1));
return bestValue(w, v, n-1, C);
}
private:
vector<vector<int>> memo;
//用[0...index]的物品填充容积为C的背包的最大价值
int bestValue(const vector<int>& w, const vector<int>& v, int index, int c){
if( index < 0 || c <= 0 )
return 0;
if( memo[index][c] != -1 )
return memo[index][c];
int res = bestValue(w, v, index-1, c);
if( c >= w[index] )
res = max(res, v[index] + bestValue(w, v, index-1, c-w[index]));
memo[index][c] = res;
return res;
}
};
int main(){
vector<int> w = {1, 2, 3};
vector<int> v = {6, 10, 12};
int C = 5;
int bestValue = Solution().knapsack01(w, v, C);
cout<<"bestValue = "<<bestValue<<endl;
return 0;
}
动态规划
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
class Solution{
//空间复杂度:O(n * C)
public:
int knapsack01(const vector<int>& w, const vector<int>& v, int C){
assert( w.size() == v.size() );
int n = w.size();
if(n == 0)
return 0;
vector<vector<int>> memo(n, vector<int>(C+1, -1));
//vector<int> memo(C+1, 0);
for(int j = 0; j <= C; j++)
memo[0][j] = (j >= w[0] ? v[0] : 0);
for(int i = 1 ; i < n; i++)
for(int j = 0; j <= C; j++){
memo[i][j] = memo[i-1][j];
if(j >= w[i])
memo[i][j] = max(memo[i][j], v[i] + memo[i-1][j-w[i]]);
}
return memo[n-1][C];
}
};
int main(){
vector<int> w = {1, 2, 3};
vector<int> v = {6, 10, 12};
int C = 5;
int bestValue = Solution().knapsack01(w, v, C);
cout<<"bestValue = "<<bestValue<<endl;
return 0;
}
鉴于上面空间复杂度为O(n * C),优化如下,此时空间复杂度O©。
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
class Solution{
public:
int knapsack01(const vector<int>& w, const vector<int>& v, int C){
assert( w.size() == v.size() );
int n = w.size();
if(n == 0)
return 0;
//vector<vector<int>> memo(n, vector<int>(C+1, -1));
vector<int> memo(C+1, 0);
for(int j = 0; j <= C; j++)
memo[j] = (j >= w[0] ? v[0] : 0);
for(int i = 1 ; i < n; i++)
for(int j = C; j >= w[i]; j--)
memo[j] = max(memo[j], v[i] + memo[j-w[i]]);
return memo[C];
}
};
int main(){
vector<int> w = {1, 2, 3};
vector<int> v = {6, 10, 12};
int C = 5;
int bestValue = Solution().knapsack01(w, v, C);
cout<<"bestValue = "<<bestValue<<endl;
return 0;
}
声明:本文只是对波波老师授课内容总结,用于交流学习。