动态规划(一)0-1背包问题

       在使用动态规划思想解决的问题中,最常见的是背包的问题,而在背包问题中,最简单的就是0-1背包。

       0-1背包的问题形式如下:有一背包,只能装重量为V的物品,有n个的物品,这些物体体积为w,价值为v,在每个物品最多装一个的情况下,怎么装物品可以让背包中的物品价值最大。该问题之所以可以用动态规划来解决,是由于将“大问题”拆解后的“小问题”存在着依赖关系,并不独立,这也是动态规划和分治最大的区别。

        在对该问题进行分析之前,可以先定义一些变量,来辅助分析。具体为:value[ i ]表示第i个物品的价值,weight[ i ]表示第i个物品的体积,dp[ i ][ j ]表示当前背包容量为j时,前i个物品最佳组合对应的价值。为方便分析,设定物品个数为4,背包重量限制为8,示例数据如下:

体积(weight) 2 3 4 5
价值(value) 3 4 5 6

         分析步骤如下:

           1、构建一张动态规划表dp,表的大小为(物品个数+1)*(背包重量限制+1)。dp[0][0]-dp[0][物品+1]和dp[0][0]-dp[0][背包重量限制+1]全为0,如下:

个数/重量 0 1 2 3 4 5 6 7 8
0 0 0 0 0 0 0 0 0 0
1 0                
2 0                
3 0                
4 0                

              2、以dp[ i ][ j ],即背包可装重量为j,第i个物品的状态来进行分析。此时可能进行的动作有如下几种:

                  1>要装入物品的重量比背包可装的重量要大,此时不能再装入新物品,即dp[ i ][ j ] = dp[i - 1][ j ];

                  2>此时能装下新物品,但具体要不要装入则需要看是否能达到最大价值,如果达不到,则和不能装入效果一样,即 dp[ i ][ j ] = dp[i - 1][ j ]。如果能装入,则dp[i - 1][j - weight[ i ]] + value[ i ]。

                      寻找最大价值的过程,就是一个逐行不断填表的过程,最终填表结果如下:

物品/重量 0 1 2 3 4 5 6 7 8
0 0 0 0 0 0 0 0 0 0
1 0 0  3 3 3 3 3 3 3 
2 0 0 3 4 4 7 7 7  7 
3 0 0  3 4 5  7 8 9 9 
4 0 0 3 4 5  7 8 9 10

        Java代码如下:

             int[ ] weight = {0,2,3,4,5};                                              //商品的重量2、3、4、5
             int[ ] value = {0,3,4,5,6};                                                //商品的价值3、4、5、6
             int bagCap = 8;                                                             //背包承受的重量限制
             int[ ][ ] dp = new int[weight.length][bagCap+1];            //动态规划表
 
             //构建动态规划表
            for (int i = 1; i <= weight.length-1; i++) {
                 for (int j = 1; j <= bagCap; j++) {
                      if (j < weight[ i ])
                           dp[ i ][ j ] = dp[i - 1][ j ];
                      else
                           dp[ i ][ j ] = Math.max(dp[i - 1][ j ], dp[i - 1][j - weight[ i ]] + value[ i ]);
                 }
            }
 
            //动态规划表的输出
            for (int i = 0; i < 5; i++) {
                 for (int j = 0; j < 9; j++) {
                     System.out.print(dp[ i ][ j ]+" ");
                  }
                 System.out.print("\n");
             }

原创文章 9 获赞 0 访问量 604

猜你喜欢

转载自blog.csdn.net/m0_37741420/article/details/105186517