题目链接:https://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=1368
题目大意
n种物品,背包容量w。每种物品体积wi,价值vi,有ci个。求背包能取的最大价值。
范围:(1 <= n <= 100, 1 <= w <= 50000, 1 <= wi <= 10000, 1 <= vi <= 10000, 1 <= ci <= 200)
思路
多重背包裸题。当总体积大于等于背包容量的时候,符合完全背包。否则,满足01背包,就是将数量ci,表示成1,2,4等二进制数相加,比如9=1+2+4+2,分成四份,体积价值加倍,然后进行01背包操作。
ac代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e5 + 5;
int dp[maxn];
int weight[maxn], value[maxn], num[maxn];
int n, s;
void bag1(int w, int v){ //01背包
for(int i = s; i >= w; i --)
dp[i] = max(dp[i], dp[i - w] + v);
}
void bag2(int w, int v){ //完全背包
for(int i = w; i <= s; i ++)
dp[i] = max(dp[i], dp[i - w] + v);
}
void bag3(int w, int v, int num){ //多重背包
if(num * w >= s) bag2(w, v);
else{
int k = 1;
while(k <= num){
bag1(k * w, k * v);
num -= k;
k <<= 1;
}
bag1(num * w, num * v); //最后剩下的
}
}
int main(){
while(~scanf("%d%d", &n, &s)){
for(int i = 1; i <= n; i ++){
scanf("%d%d%d", &weight[i], &value[i], &num[i]);
}
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i ++){
bag3(weight[i], value[i], num[i]); //对每种物品做多重背包
}
printf("%d\n", dp[s]);
}
return 0;
}