0/1背包问题简析备忘
主要就是参照百度百科来的,本文目的是自己学习备忘。
问题描述:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。
测试数据:
1
物品数 5, 背包容量 100, 重量及价格
77 92 22 22 29 87 50 46 99 90
2
物品数 8, 背包容量 200, 重量及价格
79 83 58 14 86 54 11 79 28 72 62 52 15 48 68 62
解法1,dp方法(同时打印出选了哪些物品1表示选,0表示不选):
#include <stdio.h>
#define N 5
#define V 100
#if 0
int c[V + 1] = {0, 15, 10, 35, 18, 25 };//volume = 45
int w[V + 1] = {0, 20, 15, 30, 25, 23 };
#else
int c[V + 1] = {0, 77, 22, 29, 50, 99 };//volume = 100
int w[V + 1] = {0, 92, 22, 87, 46, 90 };
#endif
int f[N][V + 1];
int flag[N + 1];
void trace_back ()
{
int i = 1;
int v = V;
for (i = N; i > 0; --i)
{
if (f[i][v] != f[i-1][v])
{
v -= c[i];
flag[i] = 1;
}
}
for (i = 1; i <= N; i++)
printf ("%d", flag[i]);
printf ("\n");
}
int main(int argc, char * argv[])
{
int i = 1;
int v = 0;
for (i = 1; i < N; ++i)
{
for (v = V; v > 0; --v)
{
if (v >= c[i])
f[i][v] = (f[i-1][v] > f[i-1][v-c[i]] + w[i]) ?
f[i-1][v] : f[i-1][v-c[i]] + w[i];
else
f[i][v] = f[i-1][v];
}
}
f[N][V] = f[i-1][V] > f[i-1][V-c[i]] + w[i] ?
f[i-1][V] : f[i-1][V-c[i]] + w[i];
printf ("Max value : %d\n", f[N][V]);
trace_back ();
return 0;
}
以上算法,空间上可以优化,既f可以用一维数组,循环部分改为如下就可以了:
//注意其中内层循环v必须是递减的,以保证后面用的f[v-c[i]]时用的是i-1状态时存下的值。
for (i = 1; i < N; ++i)
{
for (v = V; v >= c[i]; --v)
{
f[v] = f[v] > f[v - c[i]] + w[i] ?
f[v] : f[v - c[i]] + w[i];
}
}
f[V] = f[V] > f[V - c[i]] + w[i] ?
f[V] : f[V - c[i]] + w[i];
printf ("Max value : %d\n", f[V]);