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];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章