有n种物品和一个容量为v 的背包。第i种物品最多有Mi (Mi=1,k,INF)(01,完全,多重)件可用,每件耗费的空间是Ci,价值是Wi。求解将哪些物品装入背包可使这些物品的耗费的空间总和不超过背包容量,且价值总和最大。
背包初始化:
恰好装满:dp[0]=0,dp[1~n]= - INF;(负无穷)
不必装满:dp[0~n]=0;
1.01背包
for(int i=1;i<=n;i++)
for(int j=v;j>=c[i];j--)
dp[j]=max(dp[j-c[i]]+w[i],dp[j]);
2.完全背包
for(int i=1;i<=n;i++)
for(int j=c[i];j<=v;j++)
dp[j]=max(dp[j-c[i]]+w[i],dp[j]);
3.
多重背包
二进制分解 O(N*&Mi) (&Mi为M1+M2+……Mn)
void ZeroOnePack(int cost,int wei)
{
int i;
for(i = v;i>=cost;i--)
{
dp[i] = max(dp[i],dp[i-cost]+wei);
}
}
void CompletePack(int cost,int wei)
{
int i;
for(i = cost;i<=v;i++)
{
dp[i] = max(dp[i],dp[i-cost]+wei);
}
}
void MultiplePack(int cost,int wei,int cnt)
{
if(v<=cnt*cost)
{
CompletePack(cost,wei);
return ;
}
else
{
int k = 1;
while(k<=cnt)
{
ZeroOnePack(k*cost,k*wei);
cnt = cnt-k;
k = 2*k;
}
ZeroOnePack(cnt*cost,cnt*wei);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
单调队列 O(NV):
详见:多重背包讲解
const int MAX_V = 100004;
inline void pack(int f[], int V, int v, int n, int w)
{
if (n == 0 || v == 0) return;
if (n == 1) {
for (int i = V; i >= v; --i)
if (f[i] < f[i - v] + w) f[i] = f[i - v] + w;
return;
}
if (n * v >= V - v + 1) {
for (int i = v; i <= V; ++i)
if (f[i] < f[i - v] + w) f[i] = f[i - v] + w;
return;
}
int va[MAX_V], vb[MAX_V];
for (int j = 0; j < v; ++j) {
int *pb = va, *pe = va - 1;
int *qb = vb, *qe = vb - 1;
for (int k = j, i = 0; k <= V; k += v, ++i) {
if (pe == pb + n) {
if (*pb == *qb) ++qb;
++pb;
}
int tt = f[k] - i * w;
*++pe = tt;
while (qe >= qb && *qe < tt) --qe;
*++qe = tt;
f[k] = *qb + i * w;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
4.二维背包
for(int i=0;i<k;i++)
{
for(int v=value[i][1];v<=m;v++)
{
for(int b=1;b<=s;b++)
{
dp[v][b]=dp[v][b]>dp[v-value[i][1]][b-1]+value[i][0]?dp[v][b]:dp[v-value[i][1]][b-1]+value[i][0];
if(dp[v][b]>=n&&m-v>=cost)
{
cost=m-v;
}
}
}
}
if(dp[m][s]<n)printf("-1\n");
else
printf("%d\n",cost);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
4.分组背包
for(int i=1;i<=N;i++)
for(int j=V;j>=0;j--)
for(int k=1;k<=j;k++)
f[j]=max(f[j],f[j-k]+A[i][k]);
详见: 《背包九讲》
转载的,看起来很好,收藏一下