背包问题之混合背包

package com.zhang.reflection.面试.算法模版.背包问题模版;

import java.util.Scanner;

/**题干一:
 * 如果将前三种混合起来,也就是说,有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),
 * 有的物品可以取的次数有一个上限(多重背包)。应该怎么求解呢?
 *
 * 题干二:
 * 有 N 种物品和一个容量是 V 的背包。
 * 物品一共有三类:
 * 第一类物品只能用1次(01背包);
 * 第二类物品可以用无限次(完全背包);
 * 第三类物品最多只能用 si 次(多重背包);
 * 每种体积是 vi,价值是 wi。
 * si=−1 表示第 i 种物品只能用1次;
 * si=0 表示第 i 种物品可以用无限次;
 * si>0 表示第 i 种物品可以使用 si 次;
 * 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
 */

public class 混合背包 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt(); // 物品个数
        int V = sc.nextInt(); // 背包总容量
        int[] dp = new int[V + 1];
        for(int i = 0; i < N; i++){
            int v = sc.nextInt(); // 体积
            int w = sc.nextInt(); // 价值
            int s = sc.nextInt(); // 数量
            if(s == 0){
                // 完全背包问题
                for(int j = v; j <= V; j++){
                    dp[j] = Math.max(dp[j], dp[j - v] + w);
                }
            }else{
                // 多重背包问题,01背包是多重背包的特例,可以一并处理
                //即要么为1个要么为多个
                s = Math.abs(s);
                int num=Math.min(s,V/v);
                for(int j = 1; num>0; j<<=1){
                    if(j>num){
                        j=num;
                    }
                    num=num-j;
                    for(int k = V; k >= j * v; k--){
                        dp[k] = Math.max(dp[k], dp[k - j * v] + j * w);
                    }
                }
            }
        }
        System.out.println(dp[V]);
    }
}
全部评论

相关推荐

牛客533433175号:更可气的是我做完这些给我拒了
点赞 评论 收藏
分享
10-07 23:57
已编辑
电子科技大学 Java
八街九陌:博士?客户端?开发?啊?
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务