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