数据结构和算法(32)之背包问题

学习数据结构和算法的日常Demo

背包问题

在这里插入图片描述

动态规划算法介绍

在这里插入图片描述

思路分析

解决类似的问题可以分解成一个个的小问题进行解决,假设存在背包容量大小分为1,2,3,4的各种容量的背包(分配容量的规则为最小重量的整数倍):
在这里插入图片描述
对于第一行(i=1), 目前只有吉他可以选择,所以
在这里插入图片描述
对于第二行(i=2),目前存在吉他和音响可以选择,所以

在这里插入图片描述
对于第三行(i=3),目前存在吉他和音响、电脑可以选择,所以
在这里插入图片描述
在这里插入图片描述

代码实现

public class 背包问题 {
    public static void main(String args[]) {
        int w[] = {1, 4, 3};               // 保存物品重量
        int val[] = {1500, 3000, 2000};   // 物品的价值
        int capacity = 4;                 // 背包容量
        int n = val.length;               // 物品个数


        // 二维数组,表
        // v[i][j]表示在前i个物品中能够放入容量为j的背包中的最大价值
        int[][] v = new int[n + 1][capacity + 1];
        // 记录放入商品的情况
        int[][] path = new int[n + 1][capacity + 1];

        // 初始化第一行,第一列
        for (int i = 0; i < v[0].length; i++) {
            v[0][i] = 0; // 第一行设置为0
        }
        for (int i = 0; i < v.length; i++) {
            v[i][0] = 0;    // 第一列设置为0
        }

        // 根据公式,算法.动态规划
        for (int i = 1; i < v.length; i++) {
            for (int j = 1; j < v[0].length; j++) {
                // 公式
                if (w[i - 1] > j) {
                    v[i][j] = v[i - 1][j];
                } else {
                    // 因为i从1开始
                    // 因此需要:w[i-1],val[i-1]
                    //v[i][j] = Math.max(v[i - 1][j], val[i - 1] + v[i - 1][j - w[i - 1]]);
                    // 为了记录商品存放到背包的情况,不能直接使用上述公式
                    if (v[i - 1][j] < val[i - 1] + v[i - 1][j - w[i - 1]]) {
                        v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];
                        // 把当前情况记录到path
                        path[i][j] = 1;
                    } else {
                        v[i][j] = v[i - 1][j];
                    }
                }
            }
        }

        for (int[] ints : v) {
            for (int i : ints) {
                System.out.print(i + " ");
            }
            System.out.println();
        }
        System.out.println("取了哪些商品?");
        // 遍历最后的放入情况
        int i = path.length - 1;  // 行最大下标
        int j = path[0].length - 1;   // 列最大下标
        // 从最后开始找
        while (i > 0 && j > 0) {
            if (path[i][j] == 1) {
                System.out.printf("第%d个商品放入背包\n", i);
                j -= w[i - 1];  // 指向前一个放到背包的商品,-1是因为i比w大1
            }
            i--;
        }
    }
}

在这里插入图片描述

GitHub:数据结构和算法源代码

发布了83 篇原创文章 · 获赞 23 · 访问量 3533

猜你喜欢

转载自blog.csdn.net/qq_44779506/article/details/105275692