動態規劃(一)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");
             }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章