[背包] CF730J Bottles 题解
第一问贪心的做出我们最少需要多少瓶子。
第二问需要一个巧妙的转换。如果我们想要转入瓶子的水最少,就应该让瓶子内本来的水最多!
所以问题转换为了,选一定数量的瓶子,这些瓶子的容量一定要大于总水量,求这些瓶子原来的水量最多有多少。
那么我们将每一个瓶子的容量当作体积,这个瓶子原来的水量当作价值,背包求即可。
特别地,由于要选一定数量的瓶子,需要增加一维度,代表选了几个瓶子。
并且增加的这一维度需要倒叙处理,相当于滚动数组的空间优化。
还有就是笔者踩的坑。动态规划的数组一定要初始化,否则可能从根本不合法的状态转移过来。
#include <bits/stdc++.h>
#define int long long
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define rep_(i, a, b) for(int i = a; i >= b; --i)
using namespace std;
constexpr int N = 105;
int ans, n, gel, sum, cnt, a[N], b[N], dp[N][N * N];
struct object {
int a, b;
inline bool operator < (const object &rhs) const {
return b > rhs.b;
}
}c[N];
signed main() {
memset(dp, -0x3f, sizeof dp);
dp[0][0] = 0;
cin >> n;
rep(i, 1, n) {
cin >> c[i].a;
gel += c[i].a;
}
rep(i, 1, n) cin >> c[i].b;
sort(c + 1, c + n + 1);
rep(i, 1, n) {
sum += c[i].b;
if(sum >= gel) {
cnt = i;
break;
}
}
rep(i, 1, n) {
rep_(j, cnt, 1) {
rep(k, c[i].b, sum) {
dp[j][k] = max(dp[j][k], dp[j - 1][k - c[i].b] + c[i].a);
}
rep(k, gel, sum) {
ans = max(ans, dp[j][k]);
}
}
}
cout << cnt << ' ' << gel - ans;
return 0;
}

浙公网安备 33010602011771号