揹包問題

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;
}
相關文章
相關標籤/搜索