二維背包問題


二維背包問題
有N件物品和一個容量為V,載重為U的背包。第i件物品的體積是a[i],重量是b[i],價值是w[i]。求解將哪些物品裝入背包可使價值總和最大

二維費用的背包問題是指:對於每件物品,具有兩種不同的費用;選擇這件物品必須同時付出這兩種代價;對於每種代價都有一個可付出的最大值(背包容量)。問怎樣選擇物品可以得到最大的價值。設這兩種代價分別為代價1和代價2,第i件物品所需的兩種代價分別為a[i]和b[i]。兩種代價可付出的最大值(兩種背包容量)分別為V和U。物品的價值為w[i]。

費用加了一維,只需狀態也加一維即可。設f[i][v][u]表示前i件物品付出兩種代價分別為v和u時可獲得的最大價值。狀態轉移方程就是:f [i][v][u]=max{f[i-1][v][u],f[i-1][v-a[i]][u-b[i]]+w[i]}。如前述方法,可以只使用二維的數組:當每件物品只可以取一次時變量v和u采用逆序的循環,當物品有如完全背包問題時采用順序的循環。當物品有如多重背包問題時拆分物品。

物品總個數的限制 
有時,“二維費用”的條件是以這樣一種隱含的方式給出的:最多只能取M件物品。這事實上相當於每件物品多了一種“件數”的費用,每個物品的件數費用均為1,可以付出的最大件數費用為M。換句話說,設f[v][m]表示付出費用v、最多選m件時可得到的最大價值,則根據物品的類型(01、完全、多重)用不同的方法循環更新,最后在f[0..V][0..M]范圍內尋找答案。

第一種,二維背包和01背包

import java.util.*;
//這是二維背包和01背包結合的情況
public class Main1 {
    
    static int INF=-10000;
    public static int beibao(int f[][],int w[],int a[],int b[],int U,int V,int T){
        for(int i=1;i<=U;i++)
            for(int j=1;j<=V;j++)
                f[i][j]=INF;
        f[0][0]=0;
        for(int i=0;i<T;i++){
            for(int j=U;j>=a[i];j--){
                for(int k=V;k>=b[i];k--){
            f[j][k]=Math.max(f[j-a[i]][k-b[i]]+w[i],f[j][k]);            
                }
            }
        }
        return f[U][V];
    }
    public static void main(String[] args) {
         Scanner sc = new Scanner(System.in);
             int U = 1000;
             int V = 1000;
             int T =5;
             int f[][]=new int[U+1][V+1];
             int w[] = {8 , 10 , 4 , 5 , 5};                      //價值 
             int a[] = {600 , 400 , 200 , 200 , 300};             //每一個的體積
             int b[] = {800 , 400 , 200 , 200 , 300};
             int t = beibao(f, w, a, b, U, V, T);
             System.out.println(t);
    }

}

 

第二種:杭電2159 二維背包加完全背包:

import java.util.*;
public class Main1{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
        int n = sc.nextInt();
        int m = sc.nextInt();
        int k = sc.nextInt();
        int s = sc.nextInt();
        int a[]=new int[k+1];
        int b[]=new int[k+1];
        int dp[][]=new int[s+1][m+1];
        for(int i=0;i<k;i++){
            a[i]=sc.nextInt();
            b[i]=sc.nextInt();
        }
            for(int i=0;i<k;i++)
                for(int j=1;j<=s;j++)
                    for(int l=b[i];l<=m;l++)
                        dp[j][l]=Math.max(dp[j][l],dp[j-1][l-b[i]]+a[i]);
            if(dp[s][m]>=n){
                for(int i=0;i<=m;i++){
                    if(dp[s][i]>=n)
                    {
                        System.out.println(m-i);
                        break;
                    }
                }
            }
            else
                System.out.println(-1);
    }
}

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM