您的当前位置:首页正文

混合背包问题

2024-11-20 来源:个人技术集锦

有 N种物品和一个容量是 V的背包。
物品一共有三类:

第一类物品只能用1次(01背包);
第二类物品可以用无限次(完全背包);
第三类物品最多只能用 si次(多重背包);
每种体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。

接下来有 N行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。

si=−1 表示第 i 种物品只能用1次;
si=0 表示第 i 种物品可以用无限次;
si>0 表示第 i 种物品可以使用 si 次;

输出格式
输出一个整数,表示最大价值。

数据范围
0<N,V≤1000

0<vi,wi≤1000

−1≤si≤1000

将01背包和完全背包转换为多重背包,再将多重背包进行二进制优化转换为01背包解决。

在本一道题当中,我们可以看到若此题为多重背包问题,那么按照数据范围来看,其实可以用多重背包问题的二进制优化方法来水过,先将01背包,完全背包转化成多重背包,01背包的话,则可以将物品数量写成1,而完全背包,则数量为(总体积(V)/该物品的体积(v[i])。再按照多重背包的思路,即将多重背包转化成一个个的二进制01背包来做即可。

代码如下:

import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        int N,V;
        Scanner scan=new Scanner(System.in);
        N=scan.nextInt();
        V=scan.nextInt();
        int[] dp=new int[V+1];
        for(int i=0;i<N;i++){
            int k=1;//多重背包优化的分组数
            int w=scan.nextInt();
            int v=scan.nextInt();
            int s=scan.nextInt();
            if(s<0)//01背包转换为多重背包
            {
                s=1;
            }
            else if(s==0)//完全背包转换为多重背包
            {
                s=V/w;
            }
            //多重背包的二进制优化
                while(s>0){
                    if(s-k<0){
                        for(int j=V;j>=s*w;j--){
                            dp[j]=Math.max(dp[j],dp[j-s*w]+s*v);
                        }
                        break;
                    }
                for(int j=V;j>=k*w;j--){
                    dp[j]=Math.max(dp[j],dp[j-k*w]+k*v);
                }
                s-=k;
                k*=2;
            }
        }
        System.out.println(dp[V]);
    }
}
显示全文