动态规划练习二(背包问题)

前言

此篇分享题目及思路来源于b站up 子烁爱学习秒懂算法

背包问题入门级难度:

问题:

在这里插入图片描述

思路:

解这类背包问题时,需要建立一个二位数组,用这个二维数组来记录每个子容量能存储的最大价值。我们要做的就是填这个数组,然后把最后一个元素(最大价值)返回。
设物品体积数组为cap[],价值数组为val[]
状态转移方程:
f( i )( j ) = max{ f( i-1 )( j ) , f( i-1 )( j-cap[i] ) + v[i] }

代码:

代码中输出了我们分析时要填的二维数组。

public class Problem04 {
    public static void main(String[] args) {
        Map<Integer, Integer> map = new LinkedHashMap<>();
        map.put(2, 3);
        map.put(3, 4);
        map.put(4, 5);
        map.put(5, 6);

        System.out.print("背包可容纳最大价值:" + getMaxValue(map, 8));

    }

    private static Integer getMaxValue(Map<Integer, Integer> gems, int capacity) {

        int[][] maxValue = new int[gems.size() + 1][capacity + 1];
        List<Integer> gemList = new ArrayList<>();
        int choose, notChoose;
        for (int i = 0; i < gems.size() + 1; i++) {
            maxValue[i][0] = 0;
        }
        for (int i = 0; i < capacity + 1; i++) {
            maxValue[0][i] = 0;
        }
        gemList.add(0);
        for (Integer gemKey : gems.keySet()) {
            gemList.add(gemKey);
        }

        for (int i = 1; i < gems.size() + 1; i++) {
            for (int j = 1; j < capacity + 1; j++) {
                if (gemList.get(i) > j) {
                    maxValue[i][j] = maxValue[i - 1][j];
                } else {
                    choose = gems.get(gemList.get(i)) + maxValue[i - 1][j - gemList.get(i)];
                    notChoose = maxValue[i - 1][j];
                    maxValue[i][j] = Math.max(choose, notChoose);
                }
            }
        }

        for (int i = 0; i < gems.size() + 1; i++) {
            for (int j = 0; j < capacity + 1; j++) {
                System.out.print(maxValue[i][j] + " ");
            }
            System.out.println();
        }

        getDetails(maxValue, gems, gemList, gems.size() + 1, capacity + 1);
        return maxValue[gems.size()][capacity];
    }

    private static void getDetails(int[][] maxValue, Map<Integer, Integer> gems, List<Integer> gemList, int rows, int cols) {

        List<Integer> details = new ArrayList<>();

        while (rows > 1 && cols > 1) {

            if (maxValue[rows - 1][cols - 1] != maxValue[rows - 2][cols - 1]) {
                details.add(rows - 1);
                rows--;
                cols = cols - 1 - gemList.get(rows - 1);
            } else {
                rows--;
            }
        }
        System.out.println("装入背包的有:");
        for (int i = 0; i < details.size(); i++) {
            System.out.println("体积为"+gemList.get(details.get(i))+",价值为"+gems.get(gemList.get(details.get(i)))+"的石头");
        }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值