动态规划解带体积的0-1背包问题(Java实现)

该博客介绍了一种三维背包问题的动态规划解决方案。题目要求在考虑物品重量、体积和价值的基础上,选择装入背包的物品以最大化总价值。作者提供了一个Java代码实现,通过输入物品个数、背包容量和容积、物品重量、体积和价值,计算并输出最大总价值及所选物品。测试用例展示了算法的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

给定n种物品和一背包。物品i的重量是wi,体积是bi,其价值为vi,背包的容量为C,容积为D。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大?在选择装入背包的物品时,对每种物品i只有两种选择,即装入背包或者不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。试设计一个解此问题的动态规划算法,并分析算法的计算复杂性。

题目分析:

说白了,学会只考虑重量和价值的动态规划解决0-1背包问题就会了这个问题,增加了一个条件所以二维变三维。

测试用例:

        Input:

                请输入物品个数:5
                请输入背包容量:8
                请输入背包容积:7
                请分别输入物品重量:3 4 6 1 2
                请分别输入物品体积:2 1 4 1 4
                请分别输入物品价值:6 5 7 3 8

        Output:

                最大总价值是:17
                被选入背包的物品的编号,质量和体积,价值分别是:
                第1个物品:3 2 6
                第4个物品:1 1 3
                第5个物品:2 4 8

代码实现:

import java.util.Scanner;

public class Knapsack {
    private static int n;//表示有多少个物品
    private static int c;//容量
    private static int d;//容积
    private static int[] weightArr;
    private static int[] volumeArr;
    private static int[] valueArr;
    private static int[][][] dp;

    public static void main(String[] 施凡奕) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入物品个数:");
        n = sc.nextInt();
        System.out.print("请输入背包容量:");
        c = sc.nextInt();
        System.out.print("请输入背包容积:");
        d = sc.nextInt();

        weightArr = new int[n + 1];
        volumeArr = new int[n + 1];
        valueArr = new int[n + 1];
        dp = new int[n + 1][c + 1][d + 1];//dp[i][j][k]i代表着第1到第i个物品,j代表的是重量,k代表的是容积,dp为最优价值
        System.out.println("请分别输入物品重量:");
        for (int i = 1; i <= n; i++) {
            weightArr[i] = sc.nextInt();
        }
        System.out.println("请分别输入物品体积:");
        for (int i = 1; i <= n; i++) {
            volumeArr[i] = sc.nextInt();
        }
        System.out.println("请分别输入物品价值:");
        for (int i = 1; i <= n; i++) {
            valueArr[i] = sc.nextInt();
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= c; j++) {
                for (int k = 1; k <= d; k++) {
                    if (j >= weightArr[i] && k >= volumeArr[i]) {
                        dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - weightArr[i]][k - volumeArr[i]] + valueArr[i]);
                    } else {
                        dp[i][j][k] = dp[i - 1][j][k];
                    }
                }
            }
        }

        System.out.println("最大总价值是:" + dp[n][c][d]);
        int x[] = new int[99];   //记录是否被选中
        for (int i = n; i > 1; i--)
            if (dp[i][c][d] == dp[i - 1][c][d]) {
                x[i] = 0;
            } else {
                x[i] = 1;
                c -= weightArr[i];
                d -= volumeArr[i];
            }
        x[1] = (dp[1][c][d] != 0) ? 1 : 0;
        System.out.println("被选入背包的物品的编号,质量和体积,价值分别是:");
        for (int i = 1; i < n + 1; i++)
            if (x[i] == 1)
                System.out.println("第" + i + "个物品:" + weightArr[i] + " " + volumeArr[i] + " " + valueArr[i]);
    }
}

运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瓦特的代码小屋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值