nyoj-289-蘋果(01揹包)

蘋果

時間限制:3000 ms  |  內存限制:65535 KB
難度:3
描述

ctest有n個蘋果,要將它放入容量爲v的揹包。給出第i個蘋果的大小和價錢,求出能放入揹包的蘋果的總價錢最大值。


輸入
有多組測試數據,每組測試數據第一行爲2個正整數,分別代表蘋果的個數n和揹包的容量v,n、v同時爲0時結束測試,此時不輸出。接下來的n行,每行2個正整數,用空格隔開,分別代表蘋果的大小c和價錢w。所有輸入數字的範圍大於等於0,小於等於1000。
輸出
對每組測試數據輸出一個整數,代表能放入揹包的蘋果的總價值。
樣例輸入
3 3
1 1
2 1
3 1
0 0
樣例輸出
2
來源
動態規劃經典問題
上傳者

ctest


//01揹包詳解
/*
題目
  有N件物品和一個容量爲V的揹包。第i件物品的重量是c[i],價值是w[i]。
求解將哪些物品裝入揹包可使這些物品的重量總和不超過揹包容量,且價值總和最大。
基本思路
    這是最基礎的揹包問題,特點是:每種物品僅有一件,可以選擇放或不放。
    用子問題定義狀態:即f[i][v]表示前i件物品恰放入一個容量爲v的揹包可以獲得的最大價值。
    則其狀態轉移方程便是:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 。 
    可以壓縮空間,f[v]=max{f[v],f[v-c[i]]+w[i]}
    這個方程非常重要,基本上所有跟揹包相關的問題的方程都是由它衍生出來的。
    所以有必要將它詳細解釋一下:“將前i件物品放入容量爲v的揹包中”這個子問題,
    若只考慮第i件物品的策略(放或不放),那麼就可以轉化爲一個只牽扯前i-1件物品的問題。
    如果不放第i件物品,那麼問題就轉化爲“前i-1件物品放入容量爲v的揹包中”,價值爲f[i-1][v];
    如果放第i件物品,那麼問題就轉化爲“前i-1件物品放入剩下的容量爲v-c[i]的揹包中”,
    此時能獲得的最大價值就是f [i-1][v-c[i]]再加上通過放入第i件物品獲得的價值w[i]。
    注意f[v]有意義當且僅當存在一個前i件物品的子集,其費用總和爲v。
    所以按照這個方程遞推完畢後,最終的答案並不一定是f[N] [V],而是f[N][0..V]的最大值。
    如果將狀態的定義中的“恰”字去掉,在轉移方程中就要再加入一項f[v-1],
    這樣就可以保證f[N] [V]就是最後的答案。至於爲什麼這樣就可以,由你自己來體會了。
*/

#include<iostream>//01揹包
#include<cstring>
using namespace std;
int main()
{
    int n,v,a[1005],b,c;
    while(cin>>n>>v)
    {
        memset(a,0,sizeof(a));
        if(n==0&&v==0)break;
        for(int i=0; i<n; i++)
        {
            cin>>b>>c; //重量和價值
            for(int j=v; j>=b; j--)//從後向前枚舉,
                if( a[j-b]+c> a[j])//a[j]取a[j-b]+c、a[j]價值較大者
                    a[j] = a[j-b]+c;
        }
        cout<<a[v]<<endl;
    }
return 0;
}


發佈了189 篇原創文章 · 獲贊 30 · 訪問量 160萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章