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];
}
}