【HDU 2602】Bone Collector(DP-01背包)

Bone Collector


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 2 31).


Sample Input
1
5 10
1 2 3 4 5
5 4 3 2 1
Sample Output
14


01背包问题:

1.

有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
状态转移方程为:

dp[i][v]=max(dp[i1][v],dp[i1][vc[i]]+w[i])

dp[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。
考虑前i件物品放入背包时,只需考虑放入第i件物品的状态。
有两种状态需要考虑:
1. 当第i件物品放入背包中时(占用容量c[i],背包剩余容量v-c[i]),前i-1件物品放入剩下的容量为v-c[i]的背包中,价值为dp[i-1][v-c[i]] +w[i]
2. 当第i件物品不放入背包中时,前i-1件物品放入背包中(背包容量为v),价值为dp[i-1][v]
当前最大价值即为两者中的最大值。每一个问题都转化为向数组之前元素扩展的子问题,一直到数组起始端。

2.

以上是二维数组实现法,接下来用另一种一维数组的实现方法。

for i=1..n
    for v=vol..0
        dp[v]=max{dp[v],dp[v-c[i]]+w[i]};

注意:要求在每次主循环中我们以v=vol..0的顺序推dp[v],这样才能保证推dp[v]时dp[v-c[i]]保存的是状态 dp[i-1][v-c[i]]的值。

代码示例:

  1. 二维数组实现
#include<iostream>
#include<cstring>
#include<algorithm>
#define MAX 1005
using namespace std;
int dp[MAX][MAX];
int c[MAX],w[MAX];
int main()
{
    int cas=1,t,vol,n;
    cin>>t;
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        memset(c,0,sizeof(c));
        memset(w,0,sizeof(w));
        cin>>n>>vol;
        for(int i=1;i<=n;i++) cin>>w[i];
        for(int i=1;i<=n;i++) cin>>c[i];
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=vol;j++)
            {
                if(j>=c[i])
                {
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
                }
                else dp[i][j]=dp[i-1][j];
            }
        }
        cout<<dp[n][vol]<<endl;
    }
    return 0;
} 

      2.一维数组实现

#include<iostream>
#include<cstring>
#include<algorithm>
#define MAX 1005
using namespace std;
int dp[MAX];
int c[MAX],w[MAX];
int main()
{
    int cas=1,t,vol,n;
    cin>>t;
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        memset(c,0,sizeof(c));
        memset(w,0,sizeof(w));
        cin>>n>>vol;
        for(int i=1;i<=n;i++) cin>>w[i];
        for(int i=1;i<=n;i++) cin>>c[i];
        for(int i=1;i<=n;i++)
        {
            for(int j=vol;j>=0;j--)
            {
                if(j>=c[i])
                {
                    dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
                }
                else dp[j]=dp[j];
            }
        }
        cout<<dp[vol]<<endl;
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/chen_yuazzy/article/details/76862709