hdu 2602 Bone Collector (0 1背包入门)

本题链接:点击打开链接

 

Bone Collector

 

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 60878    Accepted Submission(s): 25379

 

 

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

 

 

Author

Teddy

 

 

Source

HDU 1st “Vegetable-Birds Cup” Programming Open Contest

 

 

Recommend

lcy   |   We have carefully selected several similar problems for you:  1203 2159 2955 1171 2844 

 

本题题意:有一个喜欢收集骨头的人,他有一个容量为v的包,现在有n个骨头,每个骨头的价值和体积都不同,现在需要计算他的包可以装的骨头的最大价值是多少?

 

先输入一个数t,表示有t组测试数据,然后输入骨头数n和背包容量v,接下来第一行为各个骨头的价值,第二行为各个骨头的体积。

 

解题思路:直接是01背包的裸体,除开输入,就是直接的模板应用。背包也属于动态规划的一种,所以也有动态转移方程。这个题有二维动态数组的解法,也有一维的数组解法,只不过一维的解法不太好理解,也不太好说,关于背包问题的详细解题思路,大家还是看网上大神的《背包九讲》吧。

01背包的特点是:每件物品就一个,可以选择拿与不拿。提醒一下就是背包问题与贪心问题很像,但就是不能用贪心方法做,否则就错了。这个题还有一个坑点就是有体积为0的测试数据。

01背包的状态状态方程式为:

dp[i][j]=max{dp[i-1][j],dp[i-1][j-c[i]]+w[i]}

这个方程的意思就是现在就是将第i件物品放入背包中,这一件物品的体积为c[i],价值为w[i],

因此dp[i-1][j]代表的就是不将这件物品放入背包,

而dp[i-1][j-c[i]]+w[i]则是代表将第i件放入背包之后的总价值,比较这两者的价值,得出最大的价值存入现在的背包之中。

代码实现为:

 

for(int i=1; i<=n; i++)
            for(int j=0; j<=v; j++)
            {
                if(c[i]<=j)
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
                else
                    dp[i][j]=dp[i-1][j];
            }

 

本题代码:

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[1001][1001];    //非得定义为全局变量才行,不然就不能运行,我也不知道为什么
int maxx(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,v;
        int c[1001],w[1001];
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&n,&v);
        for(int i=1; i<=n; i++)
            scanf("%d",&w[i]);
        for(int i=1; i<=n; i++)
            scanf("%d",&c[i]);
        for(int i=1;i<=n;i++)
        for(int j=0; j<=v; j++) //从0开始,听说本题有体积为0的数据
        {
            if(c[i]<=j)
                dp[i][j]=maxx(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
            else
                dp[i][j]=dp[i-1][j];
        }
        printf("%d\n",dp[n][v]);
    }
    return 0;
}

 

 

然后这题还有一维的解法。不详说了,大家自己理解,前面我已经说了,也不好去解释。

状态转移方程式为:dp[j]=maxx(dp[j],dp[j-volume[i]]+value[i])

代码实现为:

 

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

 

 

 

 

 

代码:

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int maxx(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int t;
    int dp[1001];
    scanf("%d",&t);
    while(t--)
    {
        int n,v;
        int value[1001],volume[1001];
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&n,&v);
        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=0; i<n; i++)
        {
            for(int j=v; j>=volume[i]; j--)
                dp[j]=maxx(dp[j],dp[j-volume[i]]+value[i]);
        }
        printf("%d\n",dp[v]);
    }
    return 0;
}

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值