AcWing 7. 混合背包问题
原题链接
中等
作者:
烟花易冷
,
2020-09-19 15:55:30
,
所有人可见
,
阅读 530
#include <iostream>
#include <algorithm>
using namespace std;
int N, V, num, cnt = 1;
int w[1111], v[1111], s[1111], dp[1111];
int new_w[11111], new_v[11111]; // 价值&体积
int main()
{
cin >> N >> V;
for (int i = 1; i <= N; i++)
cin >> v[i] >> w[i] >> s[i];
for (int i = 1; i <= N; i++)
{
if (s[i] == -1) // 01背包
{
new_v[cnt] = v[i];
new_w[cnt++] = w[i];
}
else if (s[i] > 0) // 多重背包
{
for (int j = 1; j < s[i]; j <<= 1) //二进制拆分
{
new_v[cnt] = j * v[i]; // 存体积
new_w[cnt++] = j * w[i]; // 存价值
s[i] -= j; // 因为总共会有s[i]件i号物品,这里用二进制合并,枚举出所有情况。
}
if (s[i]) // 当s[i]>0;
{
new_v[cnt] = s[i] * v[i]; // 存体积
new_w[cnt++] = s[i] * w[i]; // 存价值
}
}
else if (s[i] == 0) // 完全背包,虽然是无限用,但是我们最多只能装v[i]/V个i号物品
{
num = 0;
while (num * v[i] <= V)
num++;
for (int k = 1; k < num; k <<= 1)
{
new_v[cnt] = k * v[i];
new_w[cnt++] = k * w[i];
num -= k;
}
if (num) // 当s[i]>0;
{
new_v[cnt] = num * v[i]; // 存体积
new_w[cnt++] = num * w[i]; // 存价值
}
}
}
for (int i = 1; i <= cnt; i++) //至此所有问题全部转变成01背包问题
for (int j = V; j >= new_v[i]; j--)
dp[j] = max(dp[j], dp[j - new_v[i]] + new_w[i]);
cout << dp[V];
system("pause");
return 0;
}