• 二维背包问题


    二维背包问题
    有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);
        }
    }
    
    }
  • 相关阅读:
    JS控制文本框输入的内容
    JavaScript属性
    无缝滚动
    CCS实例,网页栏目
    CSS特效
    HTML技巧
    如何解决问题
    判断输入的字符是不是数字
    删除txt文件内容
    能组成几个单词
  • 原文地址:https://www.cnblogs.com/ls-pankong/p/10493337.html
Copyright © 2020-2023  润新知