acm入門算法--簡單揹包問題ios
01揹包問題
問題描述:給定一組物品,每種物品都有本身的重量和價格,在限定的總重量內,咱們如何選擇,才能使得物品的總價格最高。算法
0-1揹包問題測試
Time Limit: 1 Second(s) Memory Limit: 32 MB
Total Submission(s): 1172 Accepted Submission(s): 456spa
Problem Description
給定n種物品和1個揹包,物品i的重量是wi,其價值爲vi,揹包的容量爲C。要求選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大。
Input
每組測試數據包含3行,第1行爲n和c,表示有n(0<=n<=400)個物品且揹包容量爲c (c<=1500),第二行爲這n個物品的重量wi(1<=wi<=1000),第三行爲這n個物品的價值vi。揹包容量和物品重量都爲整數。
Output
輸出裝入揹包的最大總價值,每一個答案一行。
Sample Input
5 10
2 2 6 5 4
6 3 5 4 6
Sample Output
15
算法思想:揹包問題是典型的動態規劃問題,給定一個揹包和這個揹包的承重量,怎麼放才能使揹包實現物品的最大價值。blog
01揹包問題的特色是:每種物品僅有一件,能夠選擇放或不放。(因此說是最基礎的,後面還會有徹底揹包,多重揹包,就不侷限在一件,也能夠有更多選擇)。ip
接下來咱們來確認狀態轉移方程:ci
每一件物品都有兩種選擇,若只考慮第i件物品的策略(放或不放),那麼就能夠轉化爲一個只牽扯前i-1件物品的問題。若是第i件物品重量不超過揹包的承重量(超重確定不能放),string
咱們選擇不把第i件物品放入揹包中,此時揹包實現的最大價值就等同於前i-1件物品在同等容量揹包中實現的最大價值f[i-1][c];it
若是放第i件物品,那麼問題就轉化爲「前i-1件物品放入剩下的容量爲c-w[i]的揹包中」,此時能得到的最大價值就是f [i-1][c-w[i]]再加上經過放入第i件物品得到的價值v[i]。io
設f[i][j]爲第i件物品放入揹包容量爲j的揹包中實現的最大價值,不可貴出狀態轉移方程爲:
f[i][j]=max{f[i-1][c], f[i-1][c-w[i]]+v[i]}
下面貼出代碼:
#include<iostream.h> #include<string.h> int f[402][1502],w[402],v[402]; int max(int a,int b) { return a>b?a:b; } int KnapSack(int n,int c,int w[],int v[]) { int i,j; memset(f,0,sizeof(f)); for(i=1;i<=n;i++) { for(j=1;j<=c;j++) { if(j<w[i-1])//物品重量超過揹包容量 f[i][j]=f[i-1][j]; else//選擇放或不放的最優策略 f[i][j]=max(f[i-1][j],f[i-1][j-w[i-1]]+v[i-1]); } } return f[n][c]; } int main() { int n,c; while(cin>>n>>c) { int i; for(i=0;i<n;i++) cin>>w[i]; for(i=0;i<n;i++) cin>>v[i]; int maxv=KnapSack(n,c,w,v); cout<<maxv<<endl; } return 0; }
二維揹包問題
問題描述:大致與01揹包類似,只是多了個限制條件,01揹包會了,這個也不難
二維費用揹包問題
Time Limit: 1 Second(s) Memory Limit: 32 MB
Total Submission(s): 91 Accepted Submission(s): 49
Problem Description
給定N種物品和1個揹包,物品i的體積是ai,重量是bi, 價值爲vi,揹包的體積爲V,揹包的最大承載重量W。要求選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大。
Input
每組測試數據包含4行,第1行爲N,V,W,表示有N個物品且揹包體積爲V和載重量W,第2行爲這N個物品的體積ai,第3行爲這N個物品的重量bi,第4行爲這N個物品的價值vi。
全部輸入數字都爲整數,範圍大於0,小於等於100。處理到文件結束。
Output
輸出裝入揹包的最大總價值,每一個答案一行。
Sample Input
4 3 1
1 1 1 2
2 2 1 1
3 3 1 3
Sample Output
3
算法思想:狀態轉移方程同01揹包相似,多了體積這個限制,若是第i件物品放入揹包中問題就轉化爲「前i-1件物品放入剩下的承重量爲c-w[i],體積爲v-a[i]的揹包」,
此時能得到的最大價值就是f [i-1][c-w[i]][v-a[i]]再加上經過放入第i件物品得到的價值v[i]。
設f[i][j][k]爲第i件物品放入揹包容量爲j,體積爲k的揹包中實現的最大價值,不可貴出狀態轉移方程爲:
f[i][j][k]=max{f[i-1][c][v], f[i-1][c-w[i]][v-a[i]]+v[i]}
代碼以下:
#include<iostream> #include<string> using namespace std; int a[100],v[100],w[100],f[100][100][100]; int maxV(int v1,int v2){ return v1>v2?v1:v2; } int main(){ int N,V,W; while(cin>>N>>V>>W){ int i,j,k; memset(f,0,sizeof(f)); for(i=0;i<N;i++)cin>>a[i]; for(i=0;i<N;i++)cin>>w[i]; for(i=0;i<N;i++)cin>>v[i]; for(i=0;i<N;i++){ for(j=0;j<=V;j++){ for(k=0;k<=W;k++){ if(i==0){//第一件物品 if(a[i]<=j&&w[i]<=k)//知足揹包條件限制 f[i][j][k]=v[i];//最大實現價值爲當前物品價值 } else{ if(a[i]>j||w[i]>k) f[i][j][k]=f[i-1][j][k]; else f[i][j][k]=maxV(f[i-1][j][k],f[i-1][j-a[i]][k-w[i]]+v[i]); } } } } cout<<f[N-1][V][W]<<endl; } return 0; }