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]);

递归解法如下:
#include <stdio.h>
#define N 5
#define V 100
#define MAXSIZE 10
#if 0 
int c[MAXSIZE + 1] = { 15, 10, 35, 18, 25 };//volume = 45
int w[MAXSIZE + 1] = { 20, 15, 30, 25, 23 };
#else
int c[N] = { 77, 22, 29, 50, 99 };//volume = 100
int w[N] = { 92, 22, 87, 46, 90 };
#endif
int F (int n, int v)
{
int temp1 = 0;
int temp2 = 0;
if (n == 0)
return 0;
if ( v >= c[n-1])
temp1 = F (n - 1, v - c[n-1]) + w[n-1];
temp2 = F (n - 1, v);
return temp1 > temp2 ? temp1 : temp2;
}
int main (int argc, char *argv[])
{
printf ("%d\n", F (N, V));
return 0;
}
时间和空间上都稍优一点,可见递归并不是低效的代名词。

 

 

posted @ 2011-08-10 23:27  jialejiahi  阅读(249)  评论(0编辑  收藏  举报