解决背包问题(动态规划)01背包和完全背包

14 篇文章 1 订阅
本文介绍了背包问题的两种经典类型:01背包和完全背包。01背包问题中,每种物品仅有一件,而完全背包允许有无限件相同物品。通过动态规划的方法,分别给出了两种问题的Java代码实现,用于找到在不超过背包容量的前提下,最大化物品价值的解决方案。文章还提供了代码执行的示例结果。
摘要由CSDN通过智能技术生成

1.定义

有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

2.01背包问题

说明:

在解决问题之前,为描述方便,首先定义一些变量:Vi表示第 i 个物品的价值,Wi表示第 i 个物品的体积,定义V(i,j):当前背包容量 j,前 i 个物品最佳组合对应的价值,同时背包问题抽象化(X1,X2,…,Xn,其中 Xi 取0或1,表示第 i 个物品选或不选)。

1、建立模型,即求max(V1X1+V2X2+…+VnXn);

2、寻找约束条件,W1X1+W2X2+…+WnXn<capacity;

3、寻找递推关系式,面对当前商品有两种可能性:

包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);
还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}。
其中V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i),但价值增加了v(i);

由此可以得出递推关系式:

j<w(i)      V(i,j)=V(i-1,j)
j>=w(i)     V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}
这里需要解释一下,为什么能装的情况下,需要这样求解(这才是本问题的关键所在!):

可以这么理解,如果要到达V(i,j)这一个状态有几种方式?

肯定是两种,第一种是第i件商品没有装进去,第二种是第i件商品装进去了。没有装进去很好理解,就是V(i-1,j);装进去了怎么理解呢?如果装进去第i件商品,那么装入之前是什么状态,肯定是V(i-1,j-w(i))。由于最优性原理(上文讲到),V(i-1,j-w(i))就是前面决策造成的一种状态,后面的决策就要构成最优策略。两种情况进行比较,得出最优。

解决代码:

/**
     * 01-背包
     *
     * @param capacity 背包容量
     * @param weight   物品重量数组
     * @param value    物品价值数组
     */
    public int bagProblem(int capacity, int[] weight, int[] value) {
        int row = weight.length;
        int[][] arr = new int[row + 1][capacity + 1];
        for (int i = 1; i <= row; i++) {
            for (int j = 1; j <= capacity; j++) {
                if (j < weight[i - 1]) {
                    arr[i][j] = arr[i - 1][j];
                } else {
                    arr[i][j] = Math.max(arr[i - 1][j], arr[i - 1][j - weight[i - 1]] + value[i - 1]);
                }
            }
        }
        print(arr);
        return arr[row][capacity];
    }



public void print(int[][] arr) {
        for (int[] ints : arr) {
            for (int j = 0; j < arr[0].length; j++) {
                System.out.print(ints[j] + "\t");
            }
            System.out.println();
        }
    }

结果显示:

1e1cd49c4e9a4d7d909352513598eabb.png

 3.完全背包问题

解决代码:

/**
     * 完全背包
     *
     * @param capacity 背包容量
     * @param weight   物品重量数组
     * @param value    物品价值数组
     */
    public int bagProblems(int capacity, int[] weight, int[] value) {
        int[] arr = new int[capacity + 1];
        for (int i = 0; i < weight.length; i++) {
            for (int j = weight[i]; j <= capacity; j++) {
                arr[j] = Math.max(arr[j], arr[j - weight[i]] + value[i]);
            }
        }
        return arr[capacity];
    }

结果显示:

ba3ad77760e143f38ad6f661771c73f5.png

4.总代码

package practice;

/**
 * 背包问题01
 */
public class Knapsack {

    public static void main(String[] args) {
        int[] weight = {1, 2, 4};
        int[] value = {15, 35, 45};
        Knapsack knapsack = new Knapsack();
        System.out.println(knapsack.bagProblems(4, weight, value));
    }

    /**
     * 01-背包
     *
     * @param capacity 背包容量
     * @param weight   物品重量数组
     * @param value    物品价值数组
     */
    public int bagProblem(int capacity, int[] weight, int[] value) {
        int row = weight.length;
        int[][] arr = new int[row + 1][capacity + 1];
        for (int i = 1; i <= row; i++) {
            for (int j = 1; j <= capacity; j++) {
                if (j < weight[i - 1]) {
                    arr[i][j] = arr[i - 1][j];
                } else {
                    arr[i][j] = Math.max(arr[i - 1][j], arr[i - 1][j - weight[i - 1]] + value[i - 1]);
                }
            }
        }
        print(arr);
        return arr[row][capacity];
    }

    /**
     * 完全背包
     *
     * @param capacity 背包容量
     * @param weight   物品重量数组
     * @param value    物品价值数组
     */
    public int bagProblems(int capacity, int[] weight, int[] value) {
        int[] arr = new int[capacity + 1];
        for (int i = 0; i < weight.length; i++) {
            for (int j = weight[i]; j <= capacity; j++) {
                arr[j] = Math.max(arr[j], arr[j - weight[i]] + value[i]);
            }
        }
        return arr[capacity];
    }

    public void print(int[][] arr) {
        for (int[] ints : arr) {
            for (int j = 0; j < arr[0].length; j++) {
                System.out.print(ints[j] + "\t");
            }
            System.out.println();
        }
    }

}

背包问题的解答就到此结束啦!如果你有任何问题可以再评论区留言,我会一一解答哦! 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

欲戴王冠♛必承其重

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

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

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

打赏作者

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

抵扣说明:

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

余额充值