Day32 | 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ 70. 爬楼梯 (进阶)

语言

Java

完全背包  

52. 携带研究材料(第七期模拟笔试)

题目

思路

动规五部曲思想与01背包类似,只是物品可以重复装进去了。

代码

//先遍历物品,再遍历背包
private static void testCompletePack(){
    int[] weight = {1, 3, 4};
    int[] value = {15, 20, 30};
    int bagWeight = 4;
    int[] dp = new int[bagWeight + 1];
    for (int i = 0; i < weight.length; i++){ // 遍历物品
        for (int j = weight[i]; j <= bagWeight; j++){ // 遍历背包容量
            dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
        }
    }
    for (int maxValue : dp){
        System.out.println(maxValue + "   ");
    }
}

//先遍历背包,再遍历物品
private static void testCompletePackAnotherWay(){
    int[] weight = {1, 3, 4};
    int[] value = {15, 20, 30};
    int bagWeight = 4;
    int[] dp = new int[bagWeight + 1];
    for (int i = 1; i <= bagWeight; i++){ // 遍历背包容量
        for (int j = 0; j < weight.length; j++){ // 遍历物品
            if (i - weight[j] >= 0){
                dp[i] = Math.max(dp[i], dp[i - weight[j]] + value[j]);
            }
        }
    }
    for (int maxValue : dp){
        System.out.println(maxValue + "   ");
    }
}

易错点

遍历顺序:遍历背包容量的时候,要从前开始遍历。

并且先遍历物品还是先遍历背包都可以。

518. 零钱兑换 II

零钱兑换 II

题目

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。 

题目数据保证结果符合 32 位带符号整数。

思路

根据动规五部曲进行分析:

dp数组的含义:当j时,有多少种方法加起来等于amount。

递推公式:dp[j] += dp[j - coins[i]];

在背包中找最多方法都是这个递推公式。

初始化:dp[0] = 1;从零开始累加

遍历顺序:先物品再背包,且背包正序遍历

举例推导是否正确

代码

class Solution {
    public int change(int amount, int[] coins) {
        //可以把本题看做一个完全背包问题
        //根据硬币金额凑出来总金额
        int[] dp = new int[amount + 1];
        dp[0] = 1;//初始化
        for (int i = 0; i < coins.length; i++) {
            for (int j = coins[i]; j <= amount; j++) {
                //递推公式
                dp[j] += dp[j - coins[i]];
            }
        }
        return dp[amount];
    }
}

易错点

本题只能先物品再背包,因为最后要获得的是一个组合,如果是先背包再物品会获得一个排列顺序。

377. 组合总和 Ⅳ

组合总和 Ⅳ

题目

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。

题目数据保证答案符合 32 位整数范围。

思路

与上题类似,不过本题需要求的相当于排列,上题求得算是组合。

根据动规五部曲进行分析:

dp数组的含义:当j时,有多少种方法加起来等于target。

递推公式:dp[i] += dp[i - coins[j]];

在背包中找最多方法都是这个递推公式。

初始化:dp[0] = 1;从零开始累加

遍历顺序:先背包再物品,且都是正序遍历

举例推导是否正确

代码

class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target + 1];//dp数组的含义
        dp[0] = 1;//初始化
        for (int i = 0; i <= target; i++) {
            for (int j = 0; j < nums.length; j++) {
                if (i >= nums[j]) {
                    dp[i] += dp[i - nums[j]];
                }
            }
        }
        return dp[target];
    }
}

易错点

本题是先遍历得背包容量。

70. 爬楼梯 (进阶)

57. 爬楼梯(第八期模拟笔试)

题目

思路

之前做过类似的爬楼梯,是用贪心做的。本题用动规做。

根据动规五部曲进行分析:

dp数组的含义:当j时,有多少种方法加起来等于n。

递推公式:dp[j] += dp[j - i];

在背包中找最多方法都是这个递推公式。

初始化:dp[0] = 1;从零开始累加

遍历顺序:先背包再物品,且都是正序遍历

举例推导是否正确

代码

import java.util.Scanner;
class Main{
    public static void main(String [] args){
        Scanner sc = new Scanner(System.in);
        int m, n;
        while (sc.hasNextInt()) {
            // 从键盘输入参数,中间用空格隔开
            n = sc.nextInt();
            m = sc.nextInt();

            // 求排列问题,先遍历背包再遍历物品
            int[] dp = new int[n + 1];
            dp[0] = 1;
            for (int j = 1; j <= n; j++) {
                for (int i = 1; i <= m; i++) {
                    if (j - i >= 0) dp[j] += dp[j - i];
                }
            }
            System.out.println(dp[n]);
        }
    }
}

易错点

本题采用得ACM模式了解先输入的是背包还是物品。

遍历顺序:因为他是排列问题所以先背包再物品。

总结

今天练了完全背包问题,明天继续动规问题。

加油!

滴水穿石,非一日之功。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值