DP之背包問題+記憶遞迴

來源:互聯網
上載者:User
2個問題:

1)背包問題的動態規劃解法
2)動態規劃的另一種實現方式,記憶遞迴(dp的第一篇文章就提到過,professional中也提到過),在這裡來講解,加上全面所有的文章,這一點應該可以算是動態規

劃裡最後一個沒有詳細介紹的關鍵點了

---------------------------------------------------------------------------------------------------------------------------------------------------

給定一組物品:

重量為 w1 , w2 , .......wn

價值為 v1 , v2 , .........vn

和一個稱重量為W的書包。

求這些物品的一個最有價值的子集,可以裝到書包中去。

--------------------------------------------------------------------------------------------------------------------------------------

1,背包問題

設 V[ i , j ]表示能夠放進稱重量為 j 的背包的前 i 個物品的最有價值子集的價值,目標是求V[ n , W ]

根據 V[ i , j ] 的最佳子集中是否包含物品 i,可以得到下列遞推式:

這個遞推式的意思是:如果 i 的重量已經比 j 大了,那顯然不含 i (  j-wi < 0 ), 如果 i 的重量比 j 小,那麼可能包含 i (如果包含能去到最大值的話)。

這個表可以按行也可以按列填:

實現:

package Section8;

/*第八章 動態規劃 背包問題*/

public class BackPack {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] w = { 2, 1, 3, 2 }; // 重量數組
int[] v = { 12, 10, 20, 15 }; // 價值數組
int W = 5;

int[][] result = backPack(w, v, W);

for (int i = 0; i < result.length; i++)
{
for (int j = 0; j < result[0].length; j++)
System.out.print(result[i][j] + " ");
System.out.println();
}
}

public static int[][] backPack(int[] w, int[] v, int W) {
// w是物品重量數組,v事物品價值數組,W是背包重量
// 返回表達背包問題求解過程的矩陣
int n = w.length; // w和v的長度是相同的
int[][] result = new int[n + 1][W + 1]; // 前i個物品(i從0到n),W從0到W

// 初始條件:result[0][j] = 0;result[i][0] = 0;
for (int i = 0; i <= W; i++)
result[0][i] = 0;
for (int i = 0; i <= n; i++)
result[i][0] = 0;

// 根據動態規劃的狀態轉移方程填表:這個表格可以一行一行的填,也可以一列一列的填,這裡採用一行一行的填
// 注意填表方式是動態規劃裡面非常重要的一個東西,當你填某一個位置時,它需要用到的其他位置必須都已經填好
// 所以填表的方式是跟狀態轉移方程相關滴,深層次來說,是跟動態規劃構造解的產生過程相關的

for (int i = 1; i <= n; i++) // 行數從1到n
{
for (int j = 1; j <= W; j++) // 列數從1到W
{
// 此時決定了一個i,j的位置要填:result[i][j]
if (j - w[i - 1] < 0)
result[i][j] = result[i - 1][j];
else
result[i][j] = max(result[i - 1][j], v[i - 1] + result[i - 1][j - w[i - 1]]);
}
}

return result;
}

public static int max(int m, int n) {
if (m >= n)
return m;
return n;
}

}

結果:

0     0     0     0     0     0    
0     0     12     12     12     12    
0     10     12     22     22     22    
0     10     12     22     30     32    
0     10     15     25     30     37    

寫了這麼幾個動態規劃,已經可以發現,有了遞推式後,其編程就顯得非常easy,基本上就是照著公式操作矩陣。

因此,應重點關注動態規劃的思想,怎麼去描述和刻畫問題,發現最有子結構,得到其狀態轉移方程。

-------------------------------------------------------------------------------------------------------------------------------------------------

2,記憶遞迴--動態規劃的另一種實現方式

關於什麼什麼是記憶遞迴,它的出發點是什麼,為什麼要記憶遞迴,這些在前面都提過,這裡再簡單說下:

動態規劃的核心思想之一就是記憶(或者記錄)來避免對重複子問題進行求解,然而,它並沒有避免對不必要子問題進行求解。

若將遞迴與動態規劃結合起來,就可以得到一種動態規劃的遞迴實現方式,這種方式避免了對不必要子問題進行求解。

實際上就是在遞迴的時候,在動態規劃表中先檢查要遞迴的項是否已經求出來了,如果已經求出來了,就直接返回答案,否則才去遞迴求解。

背包問題的記憶遞迴實現:

實際上,就是在V[ i , j]還沒有求出來的時候(一旦一個V[ i , j]求出來了,就不會再變,這點很重要),才去遞迴,否則就直接傳回值。

想想斐波拉契數列也可以記憶遞迴的去實現。

-------------------------------------------------------------------------------------------------------------------------------------------------

總結:

1) 背包問題的時間複雜度和空間複雜度都是 nW,2個迴圈,見代碼

2)一個關鍵點:動態規劃的另一種實現方式,記憶遞迴

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.