传送门:https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370240
题意
给一个背包,体积为c,有两类物品,第一类有n个,权值为k1,第二类有m个,权值为k2。每个物品都有自己的体积。
当把一个物品放进去之后,总贡献增加$k*$放入之后剩余体积。
问,最大贡献多少?
思路
体积越小,先让进去最后,所以要先排序,从小到大。
设f[i][j]表示放入第一类i个,第二类j个。则下一个是放什么呢? 可能是第一类下一个,也可能是第二类下一个。 $$f[i][j]=max(f[i-1][j]+k1*v,f[i][j-1]+k2*v)$$
这里的v是剩余体积,也就是V-已经放入体积。
然后注意边界的选取即可。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| ##include "bits/stdc++.h" using namespace std;
typedef long long ll;
void solve() { int _; cin >> _; while(_--) { ll k1, k2, V; cin >> k1 >> k2 >> V; int n, m; cin >> n >> m; vector<vector<ll>> f(n + 1, vector<ll>(m + 1)); vector<ll> a(n + 1), b(m + 1); for(int i = 1;i <= n; i++) cin >> a[i]; for(int i = 1;i <= m; i++) cin >> b[i]; sort(a.begin() + 1, a.begin() + n + 1); sort(b.begin() + 1, b.begin() + m + 1); for(int i = 1;i <= n; i++) a[i] += a[i - 1]; for(int i = 1;i <= m; i++) b[i] += b[i - 1]; ll ans = 0; for(int i = 0;i <= n; i++) { for(int j = 0;j <= m; j++) { if (i == 0 && j == 0) continue; if (i == 0) { if (V >= b[j]) f[i][j] = f[i][j - 1] + k2 * (V - b[j]); } else if (j == 0) { if (V >= a[i]) f[i][j] = f[i - 1][j] + k1 * (V - a[i]); } else { f[i][j] = max(f[i - 1][j] + k1 * (V - a[i] - b[j]), f[i][j - 1] + k2 * (V - a[i] - b[j])); } ans = max(ans, f[i][j]); } } cout << ans << endl; } }
signed main() { solve(); }
|
本文作者:jujimeizuo
本文地址: https://blog.jujimeizuo.cn/2021/04/08/zoj-4019-schrodingers-knapsack/
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0 协议。转载请注明出处!