简单明了动态规划求解 0-1 背包问题

问题分析: 

        0-1背包问题是一个经典的优化问题,其目标是在给定一系列物品和每个物品的价值及重量的条件下,选择物品放入背包,使得背包中物品的总价值最大,同时不超过背包的总承重。每个物品只能选择放入背包或不放入背包,因此称为0-1背包问题。0-1背包问题的求解思路主要基于动态规划。动态规划通过将问题分解为更小的子问题,并保存这些子问题的解以避免重复计算,从而高效地解决优化问题。

问题求解:

定义状态:

        设 dp[ i ] [ j ] 表示考虑前 i 个物品,且背包容量为 j 时,能获得的最大价值。

状态转移方程:

        对于第 i 个物品,有两种选择:放入背包或不放入背包。如果不放入第 i 个物品,则 dp[ i ] [ j ] = dp[ i-1 ] [ j ](即前 i-1 个物品在背包容量为 j 时的最大价值)。如果放入第 i 个物品,则dp[ i ] [ j ] = dp[ i-1 ] [ j-w[ i-1 ] ] + a[ i-1 ](即前 i-1 个物品在背包容量为 j-wt[ i-1 ] 时的最大价值加上第i个物品的价值,其中 w 是重量数组,a 是价值数组)。由于我们要找的是最大价值,所以 dp[ i ] [ j ] 应该是上述两种选择中的较大值。

同时,我们可以发现,第 i 行的最大价值只与第 i-1 行的的值有关,因此我们便可以考虑将数组压缩为一维数组。将数组压缩为一维数组后,我们可以看到第i轮的值会覆盖第 i-1 轮的值,但我们在计算状态转移方程,比较 dp[ j ] 和 dp[ j-w[ i-1 ] ] + a[ i-1 ] 时又会用到被覆盖了 dp[ j-w[ i-1 ] ] ,因此我们可以考虑进行反向遍历,这样就不会覆盖第 i-1 轮比现在背包容量小的值。

import java.util.Scanner;

public class main {

    public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);

        //在此输入您的代码...

        // 初始化参数

        System.out.print("请输入物品总数量");

        int num = scan.nextInt();

        System.out.print("请输入背包总承重");

        int vol = scan.nextInt();

        int[] w = new int[num]; // 各个物品的总量

        int[] a = new int[num]; // 各个物品的价值

        for (int i = 0;i < num;i++) {

                System.out.print("请输入第" + (i+1) + "个物品的重量");

                w[i] = scan.nextInt();

        }

        for (int i = 0;i < num;i++) {

                System.out.print("请输入第" + (i+1) + "个物品的价值");

          a[i] = scan.nextInt();

        }

        int[] dp = new int[vol+1]; // 各个容量最大价值

        // 每次取出一个物品,看不装下和能装下时哪个价值高

        for (int i = 0;i < num;i++) {

               for (int j = vol;j >= w[i];j--) {

                     dp[j] = Math.max(dp[j], dp[j-w[i]] + a[i]);

                }

        }

        System.out.print("能获取的最大价值为:" + dp[vol]);

        scan.close();

    }

}

运行结果:

请输入物品总数量5

请输入背包总承重10

请输入第1个物品的重量1

请输入第2个物品的重量4

请输入第3个物品的重量2

请输入第4个物品的重量5

请输入第5个物品的重量2

请输入第1个物品的价值1

请输入第2个物品的价值6

请输入第3个物品的价值5

请输入第4个物品的价值3

请输入第5个物品的价值1

能获取的最大价值为:13

  • 25
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值