多重背包模板:
1.多重背包(优化)
例题:
有N种物品,每种物品的数量为C1,C2......Cn。从中任选若干件放在容量为W的背包里,每种物品的体积为W1,W2......Wn(Wi为整数),与之相对应的价值为P1,P2......Pn(Pi为整数)。求背包能够容纳的最大价值。
Input
第1行,2个整数,N和W中间用空格隔开。N为物品的种类,W为背包的容量。(1 <= N <= 100,1 <= W <= 50000) 第2 - N + 1行,每行3个整数,Wi,Pi和Ci分别是物品体积、价值和数量。(1 <= Wi, Pi <= 10000, 1 <= Ci <= 200)
Output
输出可以容纳的最大价值。
Input示例
3 6 2 2 5 3 3 8 1 4 1
Output示例
9
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxm = 50005;
int dp[maxm] = { 0 }, w[105], v[105], c[105];
int main()
{
int n, i, j, sum, m, V;
scanf("%d%d", &n, &V);
for (i = 1;i <= n;i++)
scanf("%d%d%d", &v[i], &w[i], &c[i]);
for (i = 1;i <= n;i++)
{
int k = 0, temp = 1;
while (c[i] > k)
{
for (j = V;j >= v[i] * k;j--)
dp[j] = max(dp[j], dp[j - v[i] * k] + w[i] * k);
c[i] -= k;
k = temp;
temp *= 2;
}
for (j = V;j >= c[i] * v[i];j--)
dp[j] = max(dp[j], dp[j - c[i] * v[i]] + c[i] * w[i]);
}
printf("%d\n", dp[V]);
return 0;
}
2.利用01背包和完全背包
/**
* 多重背包:
* 有N种物品和一个容量为V的背包。第i种物品最多有Mi件可用,
* 每件耗费的空间是Ci,价值是Wi。
* 求解将哪些物品装入背包可使这些物品的耗费的空间总和不超过背包容量,且价值总和最大。
*/
#include <stdio.h>
#include <string.h>
int max(int a, int b){
if (a > b)return a;
return b;
}
#define maxn 100005
int c[maxn], w[maxn], num[maxn];//c:费用 w:价值 num:数量
int dp[maxn];
int V; //V:容量 V1:容量2
//01背包
void ZeroOnePack(int c, int w)
{
for (int v = V; v >= c; v--)
{
dp[v] = max(dp[v], dp[v - c] + w);
}
}
//完全背包
void CompletePack(int c, int w)
{
for (int v = c; v <= V; v++)
{
dp[v] = max(dp[v], dp[v - c] + w);
}
}
//多重背包
void MultiplePack(int c, int w, int num)
{
if (c * num >= V)
{
CompletePack(c, w);
}
else
{
int k = 1;
while (k < num)
{
ZeroOnePack(k*c, k*w);
num -= k;
k <<= 1;
}
ZeroOnePack(num*c, num*w);
}
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n;
scanf("%d%d", &V, &n);
for (int i = 1; i <= n; i++)
scanf("%d%d%d", &c[i], &w[i], &num[i]);
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
MultiplePack(c[i], w[i], num[i]);
printf("%d\n", dp[V]);
}
return 0;
}
/*
1
10 5
5 1 1
4 2 1
3 3 1
2 4 1
1 5 1
**
14
*/