使用动态规划解决01背包问题(Java)

动态规划的基本介绍

在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。因此各个阶段决策的选取不能任意确定,它依赖于当前面临的状态,又影响以后的发展。当各个阶段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线.这种把一个问题看作是一个前后关联具有链状结构的多阶段过程就称为多阶段决策过程,这种问题称为多阶段决策问题。在多阶段决策问题中,各个阶段采取的决策,一般来说是与时间有关的,决策依赖于当前状态,又随即引起状态的转移,一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义,称这种解决多阶段决策最优化的过程为动态规划方法。

注意

  • 动态规划算法与分治算法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
  • 与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)
  • 动态规划可以通过填表的方式来逐步推进,得到最优解。

01背包问题介绍

问题介绍:01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2至Wn,与之相对应的价值为P1,P2至Pn。01背包是背包问题中最简单的问题。01背包的约束条件是给定几种物品,每种物品有且只有一个,并且有权值和体积两个属性。在01背包问题中,因为每种物品只有一个,对于每个物品只需要考虑选与不选两种情况。如果不选择将其放入背包中,则不需要处理。如果选择将其放入背包中,由于不清楚之前放入的物品占据了多大的空间,需要枚举将这个物品放入背包后可能占据背包空间的所有情况。

代码实现

package com.athome.dynamicprogramming;

import java.util.Arrays;

/**
 * Description:
 * Author:江洋大盗
 * Date:2021/1/17 16:47
 */
public class BackpackProblem {
    public static void main(String[] args) {
        int[] weight = {1, 5, 3, 4};//表示物品的重量
        int[] value = {1500, 2500, 1200, 1800};//表示物品的价值
        int w = 10;//表示背包的最大承重
        int n = weight.length;//表示物品的个数
        int[][] maxVal = new int[n + 1][w + 1];//v[i][j]表示在前i个物品中能够装入容量为j的背包中的最大价值
        int[][] mark = new int[n + 1][w + 1];//记录哪个物品被放进背包

        //初始化条件
        for (int i = 0; i < w + 1; i++) {
            maxVal[0][i] = 0;
        }
        for (int i = 0; i < n + 1; i++) {
            maxVal[i][0] = 0;
        }

        //动态规划
        for (int i = 1; i < maxVal.length; i++) {
            for (int j = 1; j < maxVal[i].length; j++) {
                if (weight[i - 1] > j) {
                    //如果第i-1个物品(因为i从1开始)的重量小于当前背包重量
                    maxVal[i][j] = maxVal[i - 1][j];
                } else {
                    if (maxVal[i - 1][j] < value[i - 1] + maxVal[i - 1][j - weight[i - 1]]) {
                        //如果上一次规划的最大价值小于当前物品的价值和上一次规划的重量减去当前物品重量的价值总和。
                        maxVal[i][j] = value[i - 1] + maxVal[i - 1][j - weight[i - 1]];
                        mark[i][j] = 1;//记录
                    } else {
                        maxVal[i][j] = maxVal[i - 1][j];
                    }
                }
            }
        }

        //查看二维数组
        for (int[] arr : maxVal) {
            System.out.println(Arrays.toString(arr));
        }

        //列出最终方案
        int i = mark.length - 1;
        int j = mark[0].length - 1;
        while (i > 0 && j > 0) {
            if (mark[i][j] == 1) {
                System.out.println("第" + i + "个商品放入了背包");
                j -= weight[i - 1];
            }
            i--;
        }
    }
}

测试结果
测试结果


结语

只要能收获甜蜜,荆棘丛中也有蜜蜂忙碌的身影,未来的你一定会感谢现在努力的自己。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值