问题描述:一个背包容量为V,有N件不同类别的物品体积和价值分别为:v[i], w[i],把这些物品装入背包中保证背包中物品的价值最高。背包问题分为以下几种:
一、0/1背包问题
1、算法描述:背包里的物品不能有重复,属于不同类别;
2、算法方程式:f[i][v] = max{f[i-1][v], f[i-1][v - c[i]] + w[i]};
3、算法举例:列(物品类别) 行(背包容量) 行列交叉得到背包内物品的价值
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
0 | 0 | 0 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
1 | 0 | 0 | 3 | 4 | 4 | 7 | 7 | 7 | 7 | 7 |
2 | 0 | 0 | 3 | 4 | 5 | 7 | 8 | 9 | 9 | 12 |
3 | 0 | 0 | 3 | 4 | 5 | 7 | 8 | 10 | 11 | 12 |
4、源代码:
#include <stdio.h>
static int f[10] = {0};
static const int V = 9;
static const int c[4] = {2, 3, 4, 5};
static const int w[4] = {3, 4, 5, 7};
void ZeroOnePack(int cost, int weight)
{
for(int v = V; v >= cost; -- v)
{
f[v] = (f[v] > f[v - cost] + weight) ? f[v] : f[v - cost] + weight;
}
}
int main(int argc, char* argv[])
{
for(int i = 0; i < n; ++ i)
{
ZeroOnePack(c[i], w[i]);
}
printf("%d", f[V]);
return 0;
}
二、完全背包问题
1、算法描述:背包中属于同一类别的物品可以重复,且每种类别物品数量不限;
2、算法方程式:f[i][v] = max{f[i-1][v], f[i-1][v - k * c[i]] + k * w[i]}(0=<k*c[i]<=V);
3、算法举例:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
0 | 0 | 0 | 3 | 3 | 6 | 6 | 9 | 9 | 12 | 12 |
1 | 0 | 0 | 3 | 4 | 6 | 7 | 9 | 10 | 12 | 13 |
2 | 0 | 0 | 3 | 4 | 6 | 7 | 9 | 10 | 12 | 13 |
3 | 0 | 0 | 3 | 4 | 6 | 7 | 9 | 10 | 12 | 13 |
4、源代码:
#include <stdio.h>
static int f[10] = {0};
static const int V = 9;
static const int c[4] = {2, 3, 4, 5};
static const int w[4] = {3, 4, 5, 7};
void CompletePack(int cost, int weight)
{
for(int v = cost; v <= V; ++ v)
{
f[v] = (f[v] > f[v - cost] + weight) ? f[v] : f[v - cost] + weight;
}
}
int main(int argc, char* argv[])
{
for(int i = 0; i < n; ++ i)
{
CompletePack(c[i], w[i]);
}
printf("%d", f[V]);
return 0;
}
三、多重背包问题
1、算法描述:背包中属于同一类别的物品可以重复,但第i种物品数量最大量为n[i];
2、算法方程式:f[i][v]=max{f[i-1][v - k * c[i]] + k * w[i]}(0=<k<=n[i]);
3、源代码:
#include <stdio.h>
static int f[10] = {0};
static const int V = 9;
static const int n[4] = {2, 1, 1, 1};
static const int c[4] = {2, 3, 4, 5};
static const int w[4] = {3, 4, 5, 7};
//0/1背包解法
void ZeroOnePack(int cost, int weight)
{
for(int v = V; v >= cost; -- v)
{
f[v] = (f[v] > f[v - cost] + weight) ? f[v] : f[v - cost] + weight;
}
}
//完全背包解法
void CompletePack(int cost, int weight)
{
for(int v = cost; v <= V; ++ v)
{
f[v] = (f[v] > f[v - cost] + weight) ? f[v] : f[v - cost] + weight;
}
}
//多重背包解法
void MultiplePack(int cost, int weight, int amount)
{
if(cost * amount >= V)
{
CompletePack(cost, weight);
return ;
}
int k = 1;
while(k < amount)
{
ZeroOnePack(k * cost, k * weight);
amount -= k;
k *= 2;
}
ZeroOnePack(amount * cost, amount * weight);
}
int main(int argc, char* argv[])
{
for(int i = 0; i < 4; ++ i)
{
MultiplePack(c[i], w[i], n[i]);
}
printf("%d", f[V]);
return 0;
}