揹包問題

揹包問題

整理自 杭州電子科大劉春英老師PPT及《揹包九講》崔天翼ios

問題模型

給你一個容量爲V的揹包和若干種物品,在必定的限制條件下(每種物品都佔用必定容量),問最多能放進多少價值的物品?spa

和動態規劃的聯繫:揹包的每一個容量就是「狀態」,選擇每一個物品就是「狀態的決策」。code

01 揹包

問題描述ip

有N件物品和一個容量爲V的揹包。第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使價值總和最大。ci

問題特色get

每種物品僅有一件,能夠選擇放或不放,用子問題定義狀態:即f[i][v]表示前i件物品恰放入一個容量爲v的揹包能夠得到的最大價值。string

狀態轉移方程產品

\(f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}\)it

徹底揹包

問題描述io

有N種物品和一個容量爲V的揹包,每種物品都有無限件可用。第i種物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使這些物品的費用總和不超過揹包容量,且價值總和最大。

問題特色

按照01思路的想法,策略從取或者不取變成每種取多少個

狀態轉移方程

\(f[i][v]=max{f[i-1][v-kc[i]]+kw[i] | 0\ge kc[i]\le v}\)

多重揹包

問題描述

有 N 種物品和一個容量爲 V 的揹包。第 i 種物品最多有 M i 件可用,每件耗費的
空間是 \(C_i\) ,價值是 \(W_i\) 。求解將哪些物品裝入揹包可以使這些物品的耗費的空間總和不超
過揹包容量,且價值總和最大。

例題

  1. (HDU 2602) 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 ?
#include <iostream>
#include <cstring>
#define maxn 1010

using namespace std;
int volume[maxn]={0};
int value[maxn]={0};
int dp[maxn]={0};
int main(){
    int t,n,v,i,j;
    cin >> t;
    while(t--){
        memset(volume,0,sizeof(volume));
        memset(value,0,sizeof(value));
        memset(dp,0,sizeof(dp));
        cin >> n >> v;
        for(i=0;i<n;i++)
            cin >> value[i];
        for(i=0;i<n;i++)
            cin >> volume[i];
        if(n==0 || v==0){
            cout <<  '0'<< endl;
            continue;
        }
        for(i=0;i<n;i++){
            for(j=v;j>=volume[i];j--){
                dp[j] = max(dp[j],dp[j-volume[i]]+value[i]);
            }
        }
         cout << dp[v] << endl;
    }   
}
  1. (HDU1248) 咱們這裏有三種道具,血瓶150塊一個,魔法藥200塊一個,無敵藥水350塊一個." 共有N元,求結餘最少;
#include <iostream>
#include <cstring>
#define maxn 10001

using namespace std;

int cost[3]={150,200,350};
int value[3]={150,200,350};
int dp[maxn]={0};
int main(){
    int t,n,i,j,out=0;
    cin >> t;
    while(t--){
        out = 0;
        memset(dp,0,sizeof(dp));
        cin >> n;
        if(n<150){
            cout << n << endl;
            continue;
        }   
        for(i=0;i<3;i++){
            for(j=0;j<=n;j++){
                if(j>=cost[i]){
                    dp[j] = max(dp[j],dp[j-cost[i]]+value[i]);
                    out = max(out,dp[j]);
                }
            }
        }
        cout << n-out << endl;       
    }
}
  1. (HDU2191)急!災區的食物依然短缺!
    爲了挽救災區同胞的生命,心繫災區同胞的你準備本身採購一些糧食支援災區,如今假設你一共有資金n元,而市場有m種大米,每種大米都是袋裝產品,其價格不等,而且只能整袋購買。
    請問:你用有限的資金最多能採購多少公斤糧食呢?

    思路一:轉化爲01揹包問題,把全部的物品都做爲候選項,判斷這個物體是否放;簡單直觀;

#include <iostream>
#include <cstring>

using namespace std;

struct rice{
    int p;
    int h;
    int c;
}rices[2001];

int c,n,m,num,i,j;
int dp[2001]={0};
int main(){
    cin >> c;
    while(c--){
        memset(dp,0,sizeof(dp));
        memset(rices,0,sizeof(rices));
        cin >> n >> m;
        for (i=0,j=0;i<m;i++,j++){
            cin >> rices[j].p;
            cin >> rices[j].h;
            cin >> num;
            for (int k=0;k<num-1;k++){
                rices[k+1+j].p = rices[j].p;
                rices[k+1+j].h = rices[j].h;
            }
            j += num-1;
        }
        num = j;
        int maxo = 0;
        for(int i=0;i<num;i++){
            for(int j=n;j>=rices[i].p;j--){
                dp[j] = max(dp[j],dp[j-rices[i].p]+rices[i].h);
                //maxo = max(maxo,dp[j]);
            }
        }
        cout << dp[n] << endl;
    }
}
相關文章
相關標籤/搜索