[背包] 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;
}
posted @ 2025-10-27 10:13  「癔症」  阅读(2)  评论(0)    收藏  举报