01背包讲解搭配题目:HDU2602 Bone Collector

Bone Collector

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

01背包中,最重要的就是理解动态规划的过程,这道题中,大概意思就是有一堆骨头,有各自的价值和体积,问在背包体积为V的情况下,所能装的骨头的最大价值是多少。
value代表骨头的价值, weight代表骨头的体积(写代码时写错了,将错就错吧)
dp代表动态规划背包的体积。(dp[5]代表背包体积为5时,所装的最大骨头价值,dp[20]代表背包体积为20时,所装的最大骨头价值)

先模拟一下核心代码的过程
因为(背包体积)V=10,所以dp需要用到的范围是dp[1]到dp[10],代表背包体积为1到体积为10,各自能装的最大骨头价值
第一块骨头价值是1,体积为5时,下面为动态规划过程中dp所能装的最大价值
这里写图片描述
因为第一块骨头体积为5,所以只有dp[5]以后体积才大于等于5,故而dp[1]到dp[4]装不了骨头,价值为0。第一块骨头价值为1,所以,dp[5]到dp[10]的数值都为1。

接下来很关键的两步!!!
第一个“ temp=value[i]+dp[j-weight[i]] ”,temp是一个中间变量,作用只是用来存储数据,用来比较数据,temp存储的是:假如把当前骨头拿进背包中,背包所装骨头的价值,而 i 是骨头数组的下标,value[i]指的是当前骨头的价值,而dp[ j - weight[ i ] ]中,j 指的是当前dp的下标,所以呢代表现在背包体积为 j ,现在temp是把这块骨头要算进去,所以呢,当前骨头的价值value[i]要算进去吧,把这块骨头算进去,可能还有空余的空间,所以呢,“ j - weight[ i ] ”代表的就是剩余的空间。
dp[ j - weight[ i ] ]就是剩下的空间所能装的最大价值,所以temp代表的就是当前骨头装进去所能达到的最大价值,之后在if(dp[j ] < temp)做出判断,假如temp>dp[j],代表的就是当前骨头装进去所能达到的价值比不装的还要多,所以能把dp[j]的数据更新为temp,假如还有点懵,没事,继续看下去。
“ for(int j=V;j>=weight[i];j–) ”,这一步,每一块骨头都需要遍历整个dp数组,因为每一块骨头只有一块,所以呢,遍历dp时,需要从大到小遍历,防止骨头重复使用多次,前面那一步temp=value[i]+dp[j-weight[i]] ,dp[j-weight[i]]是比当前的dp[j]还小的,假如是从小到大,会先更新小的,但是到后面会造成一骨多用

第二块骨头价值为2,体积是4
这里写图片描述

后面的就依次类推了
代码如下,已经是AC过了,如果有什么问题,可以在留言区留言

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    int T;
    int N,V;//骨头数,真正的背包体积
    int value[1009],weight[1009],dp[1009]; //骨头价值,骨头体积,动态的背包体积
    int temp;
    cin>>T;
    while(T--)
    {
        cin>>N>>V;
        for(int i=0;i<N;i++)
        {
            cin>>value[i];
        }
        for(int i=0;i<N;i++)
        {
            cin>>weight[i];
        }
        memset(dp,0,sizeof(dp));//把dp数组中所有的数初始化为0

        //以下为核心代码
        //从第一个骨头开始到最后一根骨头
        for(int i=0;i<N;i++)
        {
            //书包体积从V到weight[i],
            for(int j=V;j>=weight[i];j--)
            {
                temp=value[i]+dp[j-weight[i]];
                //value  
                if(dp[j]<temp)
                dp[j]=temp;
            }
        }
        cout<<dp[V];
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值