// 用 [0...index]的物品,填充容积为c的背包的最大价值
int bestValue(const vector<int> &w, const vector<int> &v, int index, int c){
if(c <= 0 || index < 0)
return 0;
if(memo[index][c] != -1)
return memo[index][c];
int res = bestValue(w, v, index-1, c); //第index个物品 直接不要
if(c >= w[index])
res = max(res, v[index] + bestValue(w, v, index - 1, c - w[index]));
memo[index][c] = res;
return res;
}
public:
int knapsack01(const vector<int> &w, const vector<int> &v, int C){
assert(w.size() == v.size() && C >= 0);
int n = w.size();
if(n == 0 || C == 0)
return 0;
memo.clear();
for(int i = 0 ; i < n ; i ++)
memo.push_back(vector<int>(C + 1, -1));
return bestValue(w, v, n - 1, C);
}
};
int main() {
int n, W;
cin >> n >> W;
int v, w;
vector<int> vs, ws;
for(int i = 0 ; i < n ; i ++){
cin >> w >> v;
vs.push_back(v);
ws.push_back(w);
}
/// 背包问题
/// 动态规划
/// 时间复杂度: O(n * C) 其中n为物品个数; C为背包容积
/// 空间复杂度: O(n * C)
class Knapsack01{
public:
int knapsack01(const vector<int> &w, const vector<int> &v, int C){
assert(w.size() == v.size() && C >= 0);
int n = w.size();
if(n == 0 || C == 0)
return 0;
/// 背包问题
/// 动态规划改进: 滚动数组
/// 时间复杂度: O(n * C) 其中n为物品个数; C为背包容积
/// 空间复杂度: O(C), 实际使用了2*C的额外空间
class Knapsack01{
public:
int knapsack01(const vector<int> &w, const vector<int> &v, int C){
assert(w.size() == v.size() && C >= 0);
int n = w.size();
if( n == 0 && C == 0 )
return 0;
// 求s1[0...m]和s2[0...n]的最长公共子序列的长度值
int __LCS(const string &s1, const string &s2, int m, int n){
if(m < 0 || n < 0)
return 0;
if(memo[m][n] != -1)
return memo[m][n];
int res = 0;
if(s1[m] == s2[n])
res = 1 + __LCS(s1, s2, m - 1, n - 1);
else
res = max(__LCS(s1, s2, m - 1, n),
__LCS(s1, s2, m, n - 1));
memo[m][n] = res;
return res;
}