51nod 多重背包問題(動態規划)


多重背包問題

一個背包,承量有限為W,有n種物體,第i種物體,價值Vi,占用重量為 Wi,且有Ci件,選擇物品若干放入背包,使得總重量不超過背包的承重。總價值最大?

輸入
第1行,2個整數,N和W中間用空格隔開。N為物品的種類,W為背包的容量。(1 <= N <= 100,1 <= W <= 50000)
第2 - N + 1行,每行3個整數,Wi,Pi和Ci分別是物品體積、價值和數量。(1 <= Wi, Pi <= 10000, 1 <= Ci <= 200)
輸出
輸出可以容納的最大價值。
輸入示例
3 6
2 2 5
3 3 8
1 4 1
輸出示例
9
請選取你熟悉的語言,並在下面的代碼框中完成你的程序,注意數據范圍,最終結果會造成Int32溢出,這樣會輸出錯誤的答案。
不同語言如何處理輸入輸出,請查看下面的語言說明。
 
【分析】我們把第i種物品看成單個的,一個一個的,我們想想二進制,任何一個數都可以由二的冪表示。

我們試試看,比如Ci  = 14,我們可以把它化成如下4個物品:

重量是Wi,體積是Vi
重量是2 * Wi , 體積是2 * Vi
重量是4 * Wi , 體積是4 * Vi
重量是7 * Wi , 體積是7 * Vi

注意最后我們最后我們不能取,重量是8 * Wi , 體積是8 * Vi 因為那樣總的個數是1 + 2 + 4 + 8 = 15個了,我們不能多取對吧?

我們用這4個物品代替原來的14個物品,大家可以試試原來物品無論取多少個,重量和體積都可以靠我們這幾個物品湊出來,這說明我們這種分配方式和原來是等價的。

我們轉化為一般方法,對於Ci ,我們的拆分方法是:

1,2,4,8…… 同時Ci減去這些值,如果Ci不夠減了,則把最后剩余的算上,同時我們體積也對應乘以這些系數。這樣Ci個同一種物品,被我們變成了logCi個物品了。於是按照0-1背包的做法,時間復雜變為O(W * sigma(logCi))了,降了很多。
 
(關於此題還有復雜度更低的方法,留作大家思考)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <list>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std ;
ll n,m,a[50005],dp[50005];
ll b[505],w[20005],v[20005];
int main()
{
    int W,V,C,cnt=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>W>>V>>C;
        for(int j=1;;j*=2)
        {
            if(C>=j){w[cnt]=j*W;v[cnt]=j*V;C-=j;cnt++;}
            else {w[cnt]=C*W;v[cnt]=C*V;cnt++;break;}
        }
    }

    for(int i=0;i<cnt;i++)
    {
        for(int j=m;j>=w[i];j--)
        {
            dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        }
    }
    cout<<dp[m]<<endl;
    return 0 ;
}
View Code

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM