完全背包变形,外加排序,要学会变通,本题特殊之处:背包容量就是背包价值,要求的就是最大的背包容量,这需要我们找到真正的限制条件—物品数量和物品放置的限高
题目链接
AC code
#include<bits/stdc++.h>
using namespace std;
const int M = 1e6;
int dp[M], h[M], a[M], c[M];
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;cin >> n;
for (int i = 1;i <= n;i++)cin >> h[i] >> a[i] >> c[i];
for (int i = 1;i < n;i++) {//数据弱就没用sort
for (int j = i + 1;j <= n;j++) {
if (a[i] > a[j]) {
swap(a[i], a[j]);
swap(h[i], h[j]);
swap(c[i], c[j]);
}
}
}
/* for (int i = 1;i <= n;i++) {//原版完全背包
for (int k = 1;k <= c[i];k++) {
for (int j = a[i];j >= h[i];j--) {
dp[j] = max(dp[j], dp[j - h[i]] + h[i]);
}
}
}
int ans = 0;
for (int i = 1;i <= a[n];i++) ans = max(ans, dp[i]);
cout << ans; */
for (int i = 1;i <= n;i++) {//二进制优化写法
int num = min(c[i], a[i] / h[i]);
for (int k = 1;num > 0;k <<= 1) {
if (k > num)k = num;
num -= k;
for (int j = a[i];j >= h[i] * k;j--) {
dp[j] = max(dp[j], dp[j - h[i] * k] + h[i] * k);
}
}
}
int ans = 0;
for (int i = 1;i <= a[n];i++) ans = max(ans, dp[i]);
cout << ans;
return 0;
}