動態規劃之背包問題,動態規劃背包

來源:互聯網
上載者:User

動態規劃之背包問題,動態規劃背包
背包問題

有N件物品和一個容量為V的背包,第i件物品的體積是c[i],價值是w[i]。求解將哪些物品裝入背包可使價值總和最大。

狀態轉移方程:
f[i][v]=max(f[i−1][v],f[i−1][v−c[i]]+w[i])
這個方程非常重要,基本上所有跟背包相關的問題的方程都是由它衍生出來的
偽碼如下:

for i=1..N     for v=V..0         f[v]=max{f[v],f[v-c[i]]+w[i]};

如果不放第i件物品,那麼問題就轉化為”前i−1件物品放入容量為v的背包中”,價值為f[i−1][v];
如果放第i件物品,那麼問題就轉化為”前i−1件物品放入剩下的容量為v−c[i]的背包中”,此時能獲得的最大價值就是f[i−1][v−c[i]]再加上通過放入第i件物品獲得的價值w[i]。

例題

Description
辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了一個難題。醫師把他帶到一個到處都是草藥的山洞裡對他說:“孩子,這個山洞裡有一些不同的草藥,采每一株都需要一些時間,每一株也有它自身的價值。我會給你一段時間,在這段時間裡,你可以採到一些草藥。如果你是一個聰明的孩子,你應該可以讓採到的草藥的總價值最大。”
如果你是辰辰,你能完成這個任務嗎?

Input
輸入的第一行有兩個整數T(1 <= T <= 1000)和M(1 <= M <= 100),用一個空格隔開,T代表總共能夠用來採藥的時間,M代表山洞裡的草藥的數目。接下來的M行每行包括兩個在1到100之間(包括1和100)的整數,分別表示採摘某株草藥的時間和這株草藥的價值。

Output
輸出包括一行,這一行只包含一個整數,表示在規定的時間內,可以採到的草藥的最大總價值。

Sample Input

70 371 10069 11 2

Sample Output

3
解題代碼1
#include <iostream>using namespace std;int main(){    int T, M;    cin>>T>>M;    int c[101] = {0};    int w[101] = {0};    for (int i = 1; i <= M; i++)    {        cin>>w[i]>>c[i];    }    int **f = new int*[M + 1];    for (int i = 0; i <= M; i++)    {        f[i] = new int[T + 1];    }    //草藥數目為0    for (int i = 0; i <= M; i++)    {        f[i][0] = 0;    }    //採藥時間為0    for (int i = 0; i <= T; i++)    {        f[0][i] = 0;    }    int i, j;    for (i = 1; i <= M; i++)    {        for (j = 1; j <= T; j++)        {            if (j >= w[i])            {                f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + c[i]);            }            else            {                f[i][j] = f[i - 1][j];            }        }    }    cout<<f[i-1][j-1]<<endl;    //cout<<f[M][T]<<endl;    for (int i = 0; i <= M; i++)    {        delete [] f[i];    }    delete [] f;    return 0;}
解題代碼2
#include <iostream>using namespace std;int main(){    int T, M;    cin>>T>>M;    int c[101] = {0};    int w[101] = {0};    for (int i = 1; i <= M; i++)    {        cin>>w[i]>>c[i];    }    int f[1001][101] = {0};    for (int i = 1; i <= M; i++)    {        for (int j = 1; j <= T; j++)        {            if (j >= w[i])            {                f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + c[i]);            }            else            {                f[i][j] = f[i - 1][j];            }        }    }    cout<<f[M][T]<<endl;    return 0;}

代碼2多耗費一些空間,但是代碼可以簡潔很多。

解題代碼3

可以選擇使用一維數組來解決該問題,但是值得注意的是,記憶體迴圈的順序必須是V..0,即:

for i=1..N     for v=V..0         f[v]=max{f[v],f[v-c[i]]+w[i]};

如果內層迴圈為0..V,則實際的狀態方程為:
f[i][v]=max(f[i−1][v],f[i][v−c[i]]+w[i])

#include <iostream>using namespace std;int main(){    int T, M;    cin>>T>>M;    int c[101] = {0};    int w[101] = {0};    for (int i = 1; i <= M; i++)    {        cin>>w[i]>>c[i];    }    int f[101] = {0};    for (int i = 1; i <= M; i++)    {        for (int j = T; j >= 1; j--)        {            if (j >= w[i])            {                f[j] = max(f[j], f[j - w[i]] + c[i]);            }        }    }    cout<<f[T]<<endl;    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.