// #牛客春招刷题训练营# https://www.nowcoder.com/discuss/726480854079250432 // 本体解题思路来自题解中C++的第一篇 #include <climits> #include <iostream> #include <vector> using namespace std; #define ll long long #define pre(var, st, en) for (ll var = st; var < en; var++) #define endl '\n' #define kkk ' ' /*bb_makevec*/template<typename T> auto bb_makevec(T bbv_value){return bbv_value;} template<typename T1, typename T2, typename... Args> auto bb_makevec(T1 n, T2 m, Args... arg){using newtype = decltype(bb_makevec(m, arg...)); return vector<newtype>(n, bb_makevec( m, arg...));} /*print*/template<typename T> void print(T x, char bbv_end_char = 0){if (x < 10) putchar(x + '0'); else {print(x/10); putchar((x%10+'0'));} if (bbv_end_char != 0) putchar(bbv_end_char);} int main() { int n, v; cin >> n >> v; vector<int> bulk(n, 0), value(n, 0); pre(i, 0, n){ cin >> bulk[i] >> value[i]; } auto a = bb_makevec(v + 1, 0); auto pre_er = bb_makevec(v + 1, INT_MIN); pre_er[0] = 0; for (int i = 0; i < n; i++){ for (int j = v; j >= bulk[i]; j--){ pre_er[j] = max(pre_er[j], pre_er[j - bulk[i]] + value[i]);// 对于问题二,把pre_er[0]初始化为0,其余初始化为-∞(此处取INT_MIN因为题目中的物品总价值不会超过这个数的绝对值)这样只有从0开始装满的价值才是正常的(正数) a[j] = max(a[j], a[j - bulk[i]] + value[i]);// 对于问题一,就是普通的01背包,状态a[j]表示考虑前i(循环变量)个物品,装入大小为j的空间产生的最大价值;因为每次经行状态转移用到的是上一个i的前部分数据所以j从后往前,以压缩空间 } } int ans = 0; pre(i, 0, v + 1) ans = max(ans, a[i]); print(ans, endl); if (pre_er[v] < 0) print(0);// 如果是负数表示没法刚好装满 else print(pre_er[v]); return 0; } // 64 位输出请用 printf("%lld")