动态规划解决01背包问题以及完全背包问题(优化)java

一.背包问题

        有一个最大容量为C的背包,现有几个物品,每个物品都有对应的容量及价值,求在每个物品只能装一个且不超过容量的情况下,如何放置物品使背包中的价值最大

        这个每个物品最多拿一个,属于01背包问题,每个物品无限拿属于无限背包问题.

二.思路讲解

        用二维数组value来装在容量j和第i个物品情况下,能装入的'最大价值'

val[]表示每个物品的价值,w[]表示每个物体所占的容量

1.当j == 0或i == 0时,value[i][j]都为0,很好理解

2.当w[i]>j时,说明当前容量小于当前物品的容量,肯定放不进去,所以当前ij的最大价值肯定和上一个一样,value[i][j] = value[i-1][j]

3.当j>=w[i]时,容量装完当前物品后有所富余,所以得进行比较,是上一个i的最大价值大还是当前物品价值加上剩余容量价值比较大

value[i][j] = Math.max(value[i-1][j],val[i]+value[i-1][j-w[i]]);

三.上代码

class DynamicProgramming{
    public static int[][] Knapsack(int[] val,int[] w,int C){
        //val表示每个物品的单个价值
        //w表示每个物品所占容量
        //C表示背包总容量

        //value表示第i个物品在j容量下的最大价值
        int[][] value = new int[val.length+1][C+1];//考虑i == 0和j == 0,所以得加1

        //循环从1开始,因为i==0和j==0,最大价值一定为0
        for(int i = 1;i<value.length;i++){
            for(int j = 1;j<C+1;j++){

                if(w[i-1]>j){//w[i-1]是因为w数组第0个元素不是0,同理以下val数组也得-1
                    value[i][j] = value[i-1][j];//说明当前容量小于当前物品的容量
                }else {
                    value[i][j] = Math.max(value[i-1][j],val[i-1]+value[i-1][j-w[i-1]]);
                }

            }
        }
        return value;
    }
}

四.01背包优化

主要是讲空间复杂度降到O(n),压缩原先

思想和二维数组差不多,只是二维数组用的是上一行的数据,这次使用一维数组,需要滚动更新数据,

而且j得从后往前更,以放置一个物品多次放入

public static int[] Knapsack2(int[] val,int[] w,int C){
        //val表示每个物品的单个价值
        //w表示每个物品所占容量
        //C表示背包总容量

        //value表示第i个物品在j容量下的最大价值
        int[] value = new int[C+1];//考虑i == 0和j == 0,所以得加1

        //循环从1开始,因为i==0和j==0,最大价值一定为0
        for(int i = 0;i<val.length;i++){
            for(int j = value.length-1;j>=1;j--){
                if(j<w[i]){
                    value[j] = value[j];
                }else {
                    value[j] = Math.max(value[j],val[i]+value[j-w[i]]);
                }
            }
        }
        return value;
    }

五.完全背包问题

上一个小标题说j逆序是防止物品重用,那么将j正序就能得到完全背包问题的解了

//完全背包问题二维数组形式
    public static int[] Knapsack3(int[] val,int[] w,int C){
        //val表示每个物品的单个价值
        //w表示每个物品所占容量
        //C表示背包总容量

        //value表示第i个物品在j容量下的最大价值
        int[] value = new int[C+1];//考虑i == 0和j == 0,所以得加1

        //循环从1开始,因为i==0和j==0,最大价值一定为0
        for(int i = 0;i<val.length;i++){
            for(int j = value.length-1;j>=1;j--){
                for (int k = 0;k<j/w[i]+1;k++){
                    value[j] = Math.max(value[j],k*val[i]+value[j-k*w[i]]);
                }
            }
        }
        return value;
    }
    //完全背包问题一维数组最终优化
    public static int[] Knapsack4(int[] val,int[] w,int C){
        //val表示每个物品的单个价值
        //w表示每个物品所占容量
        //C表示背包总容量

        //value表示第i个物品在j容量下的最大价值
        int[] value = new int[C+1];//考虑i == 0和j == 0,所以得加1

        //循环从1开始,因为i==0和j==0,最大价值一定为0
        for(int i = 0;i<val.length;i++){
            for(int j = 0;j<value.length;j++){

                if(j<w[i]){
                    value[j] = value[j];
                }else {
                    value[j] = Math.max(value[j],val[i]+value[j-w[i]]);
                }

            }
        }
        return value;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值