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; }
[參考《挑戰程序設計》第二版及網上資料]