揹包問題學習筆記

01揹包問題
數組

題目描述優化

一我的有一個最大裝載質量爲m的揹包。如今有n件物品,它們的質量分別是W1,W2,…,Wn,它們的價值分別爲C1,C2,…,Cn。spa

若每種物品只有一件,求這我的的揹包所能裝載的最大價值。設計

輸入格式code

第一行兩個整數m,n,如題中所述。blog

第2行到第n+1行每行二個整數Wi,Ci,表示每一個物品的重量和價值,如題中所敘述。get

輸出格式io

僅一行,爲最大的價值。程序設計

輸入樣例class

10 4

2 1

3 3

4 5

7 9

輸出樣例

12

數據範圍

m<=200,n<=30

 

求解

  聲明一個數組f[j]爲總重不超過j的揹包的最大價值。因而獲得了遞推式:

    f[j]=max(f[j],f[j-w[i]]+c[i]),j>=w[i];

  而後大概就是這樣推出來的?蒟蒻講不清楚啊emmmmm直接上代碼吧orz

  下面是簡單易懂無優化的代碼:

 

 

#include <cstdio>
#define MAX_M 200
int n,m,f[MAX_M+5];    //f[i] 存儲當揹包裝載質量爲i時的最大價值 
int max(int x,int y){
    return x>y?x:y;
}
int main(){
    scanf("%d%d",&m,&n);
    for (int i=1,weight,value;i<=n;i++){    //枚舉物品 
        scanf("%d%d",&weight,&value);
        for (int j=m;j>=weight;j--)        //枚舉空間。由於使用了滾動數組,並且01揹包問題每一個物品只能拿一次,因此j要逆序枚舉。 
            f[j]=max(f[j],f[j-weight]+value);
    }
    printf("%d",f[m]);    //沒有要求剛好放滿,因此任何f[i]都是合法的初始狀態,最大的方案必定會落在f[i]中 
}  

 

 

  再觀察下數據範圍,能夠略微優化。

  下面是正式代碼,加了讀入優化,由於數據範圍不大就把int改爲short了(可是理論上不行的,誰叫這道題數據太水呢嘻嘻嘻)

 

 

#include <cstdio>
#define REG register
#define MAX_M 200
short f[MAX_M+5];    
inline short max(REG short x,REG short y){
    return x>y?x:y;
}
inline short read(){
    REG short ch=getchar(),x=0,f=1;
    while (ch<'0'||ch>'9'){
        if (ch=='-')    f=-1;
        ch=getchar();
    } while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    } return x*f;
}
int main(){
    REG short m=read(),n=read();
    for (REG short i=1,weight,value;i<=n;i++){
        weight=read(),value=read();
        for (REG short j=m;j>=weight;j--)     
            f[j]=max(f[j],f[j-weight]+value);
    }
    printf("%hd",f[m]);    
    return 0;
}  

 

 

 

[參考《挑戰程序設計》第二版及網上資料]

相關文章
相關標籤/搜索