动态规划0-1背包问题这篇博客讲的很不错 http://blog.csdn.net/yeepom/article/details/8712224
简单概述一下
问题:有n个物品,第i个物品价值为vi,重量为wi,其中vi和wi均为非负数,背包的容量为W,W为非负数。现需要考虑如何选择装入背包的物品,使装入背包的物品总价值最大。
关键是找到递推公式,递推公式中要包括所有的情形。
#include<windows.h>
#include<string.h>
#include <stdio.h>
void DP(int n, int W, int c[][18], int *v, int *wei)
{
memset(*c, 0, (W + 1) * sizeof(int));//第0行置零初始化,物品个数0
for (int i = 1; i <= n; i++)
{
c[i][0] = 0;//第0列,w=0,所有置零
for (int w = 1; w <= W; w++)
{
if (wei[i - 1] > w) //此处比较是关键
{
c[i][w] = c[i - 1][w];
}
else
{
int temp = c[i - 1][w - wei[i - 1]] + v[i - 1]; //注意wei和v数组中的第i个应该为wei[i-1]和v[i-1]
if (c[i - 1][w] > temp)
{
c[i][w] = c[i - 1][w];
}
else
c[i][w] = temp;
}
}
}
}
void findPath(int c[][18], int *x, int *wei, int n, int W)
{
int w = W;
for (int i = n; i >= 1; i--)//从高编号物品开始看
{
if (c[i][w] == c[i - 1][w])//说明i物品对价值增高不起作用,不能或者不必放
{
x[i - 1] = 0;
}
else //起作用,然后将其排除考虑i-1物品
{
x[i - 1] = 1;
w = w - wei[i - 1];
}
}
}
int main()
{
int n = 5; //物品数量最大值 >=0
int W = 17; //容量最大值 >=0
int w[] = { 3, 4, 7, 8, 9 };//重量数组int w[]={-1,3, 4, 7, 8, 9 }
int v[] = { 4, 5, 10, 11, 13 };//价值数组
int c[6][18] = { 0 }; //所有规模的价值数组
DP(n, W, c, v, w);
printf("%d
", c[5][17]);
int x[5];//物品是否放进背包情况表,0不放,1放入
findPath(c, x, w, n, W);
for (int i = 0; i < n; i++)
printf("%d
", x[i]);
system("pause");
return 0;
}
这种方法有一定的好处,能够消除递归,还能直观的得出findpath()的结果
递归实现DP
int dp(int n, int W, int *v, int *wei)
{
if (n == 0 || W == 0)
return 0;
else if (wei[n - 1] > W)
return dp(n - 1, W, v, wei);
else
{
int valueA = dp(n - 1, W - wei[n - 1], v, wei) + v[n - 1];
int valueB = dp(n - 1, W, v, wei);
return valueA > valueB ? valueA : valueB;
}
}