算法——动态规划篇——01背包问题

来源:互联网 发布:北京脱发知乎 编辑:程序博客网 时间:2024/04/28 12:23

问题描述:给定n种物品和一背包,物品i的重量是wi,其价值是pi,背包的容量是M,问如何选择装入背包中的物品总价值最大?

比如说,现在有一个背包,容量上限是10,可以放物品的个数为3,即m=10,n=3;

        物品的容量和价值分别为:

        3,4

        4,    5

        5,6

        考虑怎么做,可以从这三件物品中选出价值最大的东西来进行组合呢。

      直观上可以看出,就是后两种组合到一起,问题的关键是如何让计算机知道,来分析这个过程

      动态规划的思想:空间换时间


01234567891000000000000000444444440004555999900045669101111观察上面的表

这也是一个二维数组total[4][11];

扩大了数组的范围,用来填充下标为0的情况。。


分析:

我们考虑从三个物品中任选一个物品开始讨论,假设按顺序放,开始情况为total[1][1];表示在容量为1的情况下放1个物品,怎么放呢,由于第一物品的容量为3>1,无法放进去,所以total[1][1]的值应该沿着在容量为1放0个物品的情况下的值过来,即total[1][1]=total[0][1]=0;

同理total[1][2]=0,

那么total[1][3]呢,total[1][3]的容量为3,第一个物品对应的容量也刚好为3,所以理论上是可以将物品1放到背包里面,但是,还需要考虑的是,万一total[0][3]的价值比物品1的价值大呢,(这个地方,total[0][3]=0,只是用来说明有这种情况),

我们换一种情况来说明;

total[3][6],物品3的容量为5,小于6,可以将物品3放入到背包中,该不该放入呢,我们需要知道total[2][6]的值,为5。如果将物品3放入的话,那么容量只剩下6-5=1的容量了,原来是要放入2件物品的,即是total[2][1],有前面的表知道它为0。总的来说就是要判断total[2][6],跟total[2][1]+物品3的价值,他们两者中的大的一个,作为total[3][6]的值。

大致的思路就是这样的,具体还需要自己体会。。。

代码如下:

package hello.ant;public class AlogBeiBao {//动态规划public static void main(String[] args) {int m=10,count=3;int capacity[]={3,4,5};int value[]={4,5,6};int total[][]=new int[count+1][m+1];int i;//初始化for(i=0;i<m+1;i++){total[0][i]=0;}for(i=0;i<count+1;i++){total[i][0]=0;}for(i=1;i<count+1;i++){for(int j=1;j<m+1;j++){if(j>=capacity[i-1]){total[i][j]=max(total[i-1][j],total[i-1][j-capacity[i-1]]+value[i-1]);}else {total[i][j]=total[i-1][j];}System.out.print(total[i][j]+"  ");}System.out.println();}}static int max(int i, int j) {if(i>=j){return i;}return j;}}

结果如下,去掉了下标为0的记录:

0  0  4  4  4  4  4  4  4  4  
0  0  4  5  5  5  9  9  9  9  
0  0  4  5  6  6  9  10  11  11  


动态规划的思想就是将每一步计算的值保留下来,留作以后使用,空间换时间,还需要不断的去体会。

0 0
原创粉丝点击