2602--0-1揹包

Problem Description

Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave …
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?

Input

The first line contain a integer T , the number of cases.
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.

Output

One integer per line representing the maximum of the total value (this number will be less than 231).

Sample Input

1
5 10
1 2 3 4 5
5 4 3 2 1

Sample Output

14


因爲所求問題是n件物品,揹包限重爲m,隨着問題規模的增減,n 和m都在變化,因此很自然地想到把件數和揹包限重都作爲自變量。定義函數f(i,j)爲在1~I 件物品中選若干件裝入限重爲j的揹包中的最大價值和。

當第I件物品要裝入揹包時,f(I,j) := I-1件物品,限重爲j-w[I]的最優解+ v[I], 即:f(I,j) := f(I-1, j-w[I]) + v[I]
當然,第I件物品要裝入是有條件限制的,是什麼?
第I件物品重量小於等於揹包限重,即 w[I] <= j
當第I件物品不裝入揹包時,f(I,j) := I-1件物品,限重爲m的最優解,即:
f(I,j) := f(I-1, j)
現在已經求得裝入或者不裝入第I件物品的限重爲J的揹包的最大價值,那麼接下來應該做什麼?
比較這兩種情況下誰的價值更大,更大者爲當前問題的最優解。
if f(I,j)’ > f(I,j)’’ then
f(I,j) := f(I,j)’
else
f(I,j) := f(I,j)’’;
上述遞歸式的邊界條件是什麼?
我們知道f(I,j)的I和J都有一個取值範圍。1<=I<=n, 0 <=J<=m. 邊界條件就是當問題規模縮小到自變量下界時的函數的取值情況。
當揹包限重爲0時,無法放任何物品,此時所有的f(I,0) := 0 (1<=I<=n). 這就是邊界條件。


解1:二維數組

#include<cstdio>
#include<algorithm>
using namespace std;

int dp[1005][1005] = {0};
/*dp[i][j]爲在1~I 件物品中選若干件裝入限重爲j的揹包中的最大價值和。*/
int main()
{
    int t;
    scanf ("%d",&t);

    while (t--)
    {
        int n,v;
        scanf ("%d%d",&n,&v);

        int value[1005],volume[1005];

        for (int i=1; i<=n; i++)
        {
            scanf ("%d",&value[i]);
        }

        for (int i=1; i<=n; i++)
        {
            scanf ("%d",&volume[i]);
        }

        for (int i=1; i<=n; i++)
        {
            for (int j=0; j<=v; j++)
            {
                if (j < volume[i])
                {
                    dp[i][j] = dp[i-1][j];
                }
                else
                {
                    dp[i][j] = max(dp[i-1][j],dp[i-1][j-volume[i]]+value[i]);
                }
            }
        }
        printf ("%d\n",dp[n][v]);
    }
    return 0;
}

二維數組最重要的一點是要注意數組開闢的空間,由於這道題的要求,1005*1005將會佔大片空間,所以要定義在主函數外。


解2 :一維數組

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{
    int t;

    scanf ("%d",&t);

    while (t--)
    {
        int n,v;
        int value[1005],volume[1005];
        int i,j;

        scanf ("%d%d",&n,&v);

        for (i=0; i<n; i++)
        {
            scanf ("%d",&value[i]);
        }

        for (i=0; i<n; i++)
        {
            scanf ("%d",&volume[i]);
        }

        int dp[1005] = {0};

        for (i=0; i<n; i++)
        {
            for (j=v; j>=volume[i]; j--)
            {
                dp[j] = max(dp[j],dp[j-volume[i]]+value[i]);
            }
        }

        printf ("%d\n",dp[v]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章