01背包问题的动态规划解法

来源:互联网 发布:知达常青藤中学校介绍 编辑:程序博客网 时间:2024/06/10 05:36

参考http://www.cnblogs.com/qinyg/archive/2012/04/26/2471829.html

http://www.cnblogs.com/xy-kidult/archive/2013/03/25/2970313.html

【问题描述】

给定N中物品和一个背包。物品i的重量是Wi,其价值位Vi ,背包的容量为C。问应该如何选择装入背包的物品,使得转入背包的物品的总价值为最大?在选择物品的时候,对每种物品i只有两种选择,即装入背包或不装入背包。不能讲物品i装入多次,也不能只装入物品的一部分。因此,该问题被称为0-1背包问题。 

例如:假设现有容量10kg的背包,另外有3个物品,分别为a1,a2,a3。物品a1重量为3kg,价值为4;物品a2重量为4kg,价值为5;物品a3重量为5kg,价值为6。将哪些物品放入背包可使得背包中的总价值最大?


【分析】动态规划法的思路:将原始问题一般化,欲求背包能够获得的总价值,即欲求前i个物体放入容量为m(kg)背包的最大价值c[i][m]--使用一个数组来存储最大价值,当m取10,i取3时,即原始问题了。前i个物体放入容量为m(kg)的背包,又可以转化为前i-1个物体放入背包的问题。下面使用数学表达式描述它们两者之间的具体关系。

令V(i,j)表示在前i(1<=i<=n)个物品中能够装入容量为就j(1<=j<=C)的背包中的物品的最大价值,则可以得到如下的动态规划函数:

(1)   V(i,0)=V(0,j)=0 

(2)   V(i,j)=V(i-1,j)  j<wi  

(3)  V(i,j)=max{V(i-1,j) ,V(i-1,j-wi)+vi) } j>wi

其中(2)式表明:如果第i个物品的重量大于背包的容量,则装入前i个物品得到的最大价值和装入前i-1个物品得到的最大价值是相同的,即物品i不能装入背包;第(3)个式子表明:如果第i个物品的重量小于背包的容量,则会有以下两种情况:(a)如果把第i个物品装入背包,则背包物品的价值等于第i-1个物品装入容量位j-wi 的背包中的价值加上第i个物品的价值vi; (b)如果第i个物品没有装入背包,则背包中物品价值就等于把前i-1个物品装入容量为j的背包中所取得的价值。显然,取二者中价值最大的作为把前i个物品装入容量为j的背包中的最优解。

根据上式,对物体个数及背包重量进行递推,列出一个表格(见下表),表格来自(http://blog.csdn.net/fg2006/article/details/6766384?reload) ,当逐步推出表中每个值的大小,那个最大价值就求出来了。推导过程中,注意一点,最好逐行而非逐列开始推导,先从编号为1的那一行,推出所有c[1][m]的值,再推编号为2的那行c[2][m]的大小。这样便于理解。


【代码】

#include <stdio.h>int c[10][100] = { 0 };void knap(int m, int n){int i, j, w[10] = { 0 }, p[10] = { 0 };for (i = 1; i<n + 1; i++)scanf("%d,%d", &w[i], &p[i]);for (j = 0; j<m + 1; j++)for (i = 0; i<n + 1; i++){if (j<w[i]){c[i][j] = c[i - 1][j];continue;}else if (c[i - 1][j - w[i]] + p[i]>c[i - 1][j])c[i][j] = c[i - 1][j - w[i]] + p[i];elsec[i][j] = c[i - 1][j];}}int main(){int m, n; int i, j;printf("input the max capacity and the number of the goods:\n");scanf("%d,%d", &m, &n);printf("Input each one(weight and value):\n");knap(m, n);printf("\n");for (i = 0; i <= n; i++)for (j = 0; j <= m; j++){printf("%4d", c[i][j]);if (m == j) printf("\n");}}



0 0
原创粉丝点击