01背包 完全背包 多重背包 实现
01背包
//O(NV)
f[0][0 ~ V] = 0;
for(int i = 1; i <= n; ++i)
for(int j = 0; j <= V; ++j)
if(j < w[i]) f[i][j] = f[i - 1][j];
else f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[i]);
//O(NV) 滚动数组
f[0 ~ V] = 0;
for(int i = 1; i <= n; ++i)
for(int j = V; j >= w[i]; --j)
f[j] = max(f[j], f[j - w[i]] + v[i]);
完全背包
//O(NVK)
f[0][0 ~ V] = 0;
for(int i = 1; i <= n; ++i)
for(int j = 0; j <= V; ++j)
for(int k = 0; k * w[i] <= j; ++k)
f[i][j] = max(f[i][j], f[i - 1][j - k * w[i]] + k * v[i]);//01背包思路
//O(NV)
f[0][0 ~ V] = 0;
for(int i = 1; i <= n; ++i)
for(int j = 0; j <= V; ++j)
if(j < w[i]) f[i][j] = f[i - 1][j];
else f[i][j] = max(f[i - 1][j], f[i][j - w[i]] + v[i]);//顺序是正的
//O(NV) 滚动数组
f[0 ~ V] = 0;
for(int i = 1; i <= n; ++i)
for(int j = w[i]; j <= V; ++j)
f[j] = max(f[j], f[j - w[i]] + v[i]);
多重背包
二进制优化
//O(NVlogK)
f[0 ~ V] = 0;
for(int i = 1; i <= n; ++i){
int num = c[i];
for(int k = 1; num > 0; k <<= 1){
int mul = min(k, num);
for(int j = V; mul * w[i] <= j; --j){
f[i] = max(f[j], f[j - mul * w[i]] + mul * v[i])
}
}
}
#include <iostream>
using namespace std;
/* 多重背包 二进制拆分
* Time Complexity 大于O(N*V)
* Space Complexity O(N*V)
* 设 V <= 200 N <= 10 ,拆分后 物品总数 < 50
* 每件物品有 log n[i]种状态
*/
int maxV[201];
int weight[50]; /* 记录拆分后物体重量 */
int value[50]; /* 记录拆分后物体价值 */
int V, N;
void main()
{
int i, j;
scanf("%d %d",&V, &N);
int weig, val, num;
int count = 0;
for(i = 0; i < N; ++i)
{
scanf("%d %d %d",&weig,&val,&num);
for(j = 1; j <= num; j <= 1) // 二进制拆分
{
weight[count] = j * weig;
value[count++] = j * val;
num -= j;
}
if(num > 0)//这里是剩余的
{
weight[count] = num * weig;
value[count++] = num * val;
}
}
for(i = 0; i < count; ++i) // 使用01背包
{
for(j = V; j >= weight[i]; --j)
{
int tmp = maxV[j-weight[i]] + value[i];
maxV[j] = maxV[j] > tmp ? maxV[j] : tmp;
}
}
printf("%d",maxV[V]);
}
单调队列优化
int Q[V], f[2][V]; //单调队列,滚动数组
int z = 0;
memset(f[z], 0, sizeof f[z]);
f[z][0] = 0;
for(int i = 1; i <= n; ++i) {
memset(f[!z], 0, sizeof f[!z]);
for(int r = 0; r < w[i]; ++r) {
int L = 0, R = 0;
for(int p = 0; p * w[i] + r <= V; ++p) {
while(L < R && f[z][Q[R - 1] * w[i] + r] - Q[R - 1] * v[i]
<= f[z][p * w[i] + r] - p * v[i]) --R;
Q[R++] = p;
while(L < R && p - c[i] > Q[L]) ++L;
int q = Q[L];
f[!z][p * w[i] + r] = (f[z][q * w[i] + r] - q * v[i]) + p * v[i];
}
}
z = !z;
}