0-1背包问题

这篇博客介绍了如何用动态规划解决经典的0-1背包问题,旨在找到装入背包的最大价值。博主首先阐述了暴力求解的方法,然后详细解释了如何通过定义二维和一维dp数组来实现非暴力解法。在二维数组实现中,博主展示了如何初始化和更新dp数组,并给出了完整的Java代码示例。而在一维数组实现中,博主简化了数组结构,同样实现了动态规划的递推过程。博客最后给出了代码运行结果,展示了解决问题的具体步骤和最终答案。
摘要由CSDN通过智能技术生成





0 - 1 背包问题

1. 寻找最大价值

标准的01背包
在这里插入图片描述
装满最大价值是多少?

  1. 暴力解法就是dps深度回溯算法(装入背包 和不装背包)
  2. 非暴力使用dp方程进行动态递推

1.1 定义dp数组 dp[i][j]

i 表示列长,也就是出现的不同物品
j 表示行长,但是此时的行,为装了不同重量的可能性,也就是说0没装也是有可能的,所以(j = 最大重量 + 1)
而对应的dp[i][j] 里存放的是 价值。

在这里插入图片描述

1.2 二维数组实现

import java.util.*;

/**
 * @author JMWANG
 */
import java.io.*;

class Good {
    //价值
    int value;
    //重量
    int weight;

    Good(int v, int p) {
        this.value = v;
        this.weight = p;
    }

    Good() {
    }

    public void setValue(int v) {
        this.value = v;
    }

    public void setWeight(int p) {
        this.weight = p;
    }
}

public class Main {

    public static void main(String[] args) throws IOException {
        //最大背包重量
        int n = 4;
        //构建物品
        List listGood = new ArrayList();
        listGood.add(new Good(15, 1));
        listGood.add(new Good(20, 3));
        listGood.add(new Good(30, 4));
        //dp递推方程构建
        int[][] goods = new int[listGood.size()][n + 1];
//        for (int i = 0; i < goods.length; i++) {
//            System.out.println(Arrays.toString(goods[i]));
//        }
        dp(n, goods, listGood);
        System.out.println(goods[listGood.size() - 1][n]);
    }

    public static void dp(int N, int[][] dp, List<Good> listGood) {
        //上下层关系构建
        //dp[i][j] = max(listGood.get(i),)
        for (int i = 0; i < listGood.size(); i++) {
            for (int j = 0; j < N + 1; j++) {
                //初始化dp方程
                if (j == 0) {
                    dp[i][j] = 0;
                    continue;
                }
                if (i == 0) {
                    dp[i][j] = listGood.get(i).weight <= N ? listGood.get(i).value : 0;
                    continue;
                }

                //如果当前 重量 j < 当前物品的重量,就直接将上一层重量下传
                if (j < listGood.get(i).weight) dp[i][j] = dp[i - 1][j];
                    //如果当前 重量 j >= 当前物品的重量 ,就需要比较
                    //是垂直上一层价值更大 还是 左边+上当前物品价值更大
                else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - listGood.get(i).weight] + listGood.get(i).value);
                }
                LookDP(dp);
                System.out.println("______________________________");
            }
        }
    }

    public static void LookDP(int[][] goods) {
        for (int i = 0; i < goods.length; i++) {
            for (int j = 0; j < goods[i].length; j++) {
                System.out.print(goods[i][j] + " ");
            }
            System.out.println();
        }
    }
}

1.3 一维数组实现

    public static void testWeightBagProblem(int N, List<Good> listGood){
        int len = listGood.size();
        //定义dp数组,dp[j]表示背包容量为j时,能够获得的最大价值
        int[] dp = new int[N +1];
        //遍历顺序: 先遍历物品,再遍历背包容量
        for(int i=0;i<len;i++){
            for(int j=N;j>=listGood.get(i).weight;j--){
                System.out.println(Arrays.toString(dp));
                dp[j] = Math.max(dp[j], dp[j-listGood.get(i).weight]+listGood.get(i).value);
            }
        }
        System.out.println(Arrays.toString(dp));
        System.out.println(dp[N]);
    }






如有错误欢迎指正

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一只小小狗

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

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

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

打赏作者

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

抵扣说明:

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

余额充值