有 NN 件物品和一个容量是 V的背包。每件物品只能使用一次。
第 ii 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤1000
0<vi,wi≤1000
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例:
8
// #include<bits/stdc++.h>
// 朴素版
// using namespace std;
// const int MAXN = 1005;
// int v[MAXN]; // 体积
// int w[MAXN]; // 价值
// int f[MAXN][MAXN]; // f[i][j], j体积下前i个物品的最大价值
// int main()
// {
// int n, m;
// cin >> n >> m;
// for(int i = 1; i <= n; i++)
// cin >> v[i] >> w[i];
// for(int i = 1; i <= n; i++)
// for(int j = 1; j <= m; j++)
// {
// // 当前背包容量装不进第i个物品,则价值等于前i-1个物品
// if(j < v[i])
// f[i][j] = f[i - 1][j];
// // 能装,需进行决策是否选择第i个物品
// else
// f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
// 由于所有的选法都包含第i个物品,那么先将第i个物品去掉(所有选法都去掉),那么当前的最大值肯定不会改变(就像考试同时-10
// 分一个道理,最高分还是最高分).这样子以后再加上第i个物品的价值就行了。
// }
// cout << f[n][m] << endl;
// return 0;
// }
//优化版
//因为用到的状态j和j-vi都是<=j的,所以就可以用一维数组来算
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];
for (int i = 1; i <= n; i ++ )
for (int j = m; j >= v[i]; j -- )//为什么j从m开始?由于我们需要用到j-v[i],而这个值是小于j的,如果我们自小到大枚举的话,
//那么我们本来应该用到的这个f[j-v[i]],可能在前面已经改变,也就是状态被污染了,所以我们要逆序。
f[j] = max(f[j], f[j - v[i]] + w[i]);
cout << f[m] << endl;
return 0;
}