01背包变式
题目链接
思路
让我们来分解一下题
价格极差小于等于
3
3
3:后面价格数据范围限定所有物品极差已经小于等于
3
3
3,这句话就不用管了
那么剩下的就是一个
01
01
01背包了,每种物品最多取一次,求最大价值
但不同于
01
01
01背包的是,我们发现数据非常大(大于
1
e
9
1e9
1e9),直接打上会爆栈,所以我们想到了离散化先预处理数据
即让所有价格先减去最小的价格压缩数据,随后我们发现这样虽然不会爆栈了,但是背包容量没有变化,我们也不确定哪些能选上,所以我们需要加一个循环来判断是否选择和更新
ACcode
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M = 110;
int dp[M * 5][M], c[M], w[M];
int sv;
signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, sumv;cin >> n >> sumv;
int mi = INT_MAX;
for (int i = 1;i <= n;i++)cin >> c[i] >> w[i], mi = min(mi, c[i]), sv += c[i];
mi--;
for (int i = 1;i <= n;i++)c[i] -= mi;
sv -= n * mi;
for (int i = 1;i <= n;i++) {
for (int j = sv;j >= c[i];j--) {
for (int k = n;k >= 1;k--) {
if (j + k * mi <= sumv)dp[j][k] = max(dp[j][k], dp[j - c[i]][k - 1] + w[i]);
}
}
}
int ans = 0;
for (int i = 1;i <= sv;i++)
for (int j = 1;j <= n;j++)
ans = max(ans, dp[i][j]);
cout << ans;
return 0;
}