当前位置: 首页 > news >正文

代码随想录第三十八天| 322. 零钱兑换 279.完全平方数 139.单词拆分 动态规划:关于多重背包,你该了解这些!

322. 零钱兑换

题目描述

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

你可以认为每种硬币的数量是无限的。

力扣题目链接

322. 零钱兑换

解题思路

这个问题可以使用动态规划来解决。我们定义一个数组 dp,其中 dp[i] 表示凑成金额 i 所需的最少硬币数量。初始化 dp[0] 为 0,因为凑成金额 0 所需的硬币数量为 0。其他 dp[i] 初始化为 Integer.MAX_VALUE,表示初始状态下无法凑成金额 i

接下来,我们遍历每一种硬币,并更新 dp 数组。对于每一种硬币 coins[i],我们更新所有大于或等于 coins[i] 的金额 j 的最少硬币数量。具体来说,如果 dp[j - coins[i]] 不是初始值(即可以凑成金额 j - coins[i]),那么 dp[j] 可以更新为 min(dp[j], dp[j - coins[i]] + 1)

最后,我们检查 dp[amount] 的值。如果它仍然是 Integer.MAX_VALUE,则返回 -1,表示无法凑成总金额。否则,返回 dp[amount],即凑成总金额所需的最少硬币数量。

代码实现

class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount+1];
        for(int i=1; i<amount+1; i++){
            dp[i] = Integer.MAX_VALUE;
        }
        for(int i=0; i<coins.length; i++){
            for(int j=coins[i]; j<amount+1; j++){
                if(dp[j-coins[i]] != Integer.MAX_VALUE) {
                    dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
                }
            }
        }
        return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
    }
}

279. 完全平方数

题目描述

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的最少数量。
完全平方数是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

力扣题目链接

279. 完全平方数

解题思路

这个问题同样可以使用动态规划来解决。我们定义一个数组 dp,其中 dp[i] 表示组成和为 i 的完全平方数的最少数量。初始化 dp[0] 为 0,因为组成和为 0 的完全平方数的最少数量为 0。其他 dp[i] 初始化为 Integer.MAX_VALUE,表示初始状态下无法组成和为 i。
接下来,我们遍历所有的完全平方数,并更新 dp 数组。对于每一个完全平方数 ii,我们更新所有大于或等于 ii 的和 j 的最少完全平方数数量。具体来说,如果 dp[j - ii] 不是初始值(即可以组成和为 j - ii),那么 dp[j] 可以更新为 min(dp[j], dp[j - i*i] + 1)。
最后,我们返回 dp[n],即组成和为 n 的完全平方数的最少数量。

代码实现

class Solution {
    public int numSquares(int n) {
        int max = Integer.MAX_VALUE;
        int[] dp = new int[n+1];
        for(int i=1; i<n+1; i++){
            dp[i] = max;
        }
        dp[0] = 0;
        for(int i=1; i*i<=n; i++){
            for(int j=i*i; j<n+1; j++){
                dp[j] = Math.min(dp[j], dp[j - i*i] + 1);
            }
        }
        return dp[n];
    }
}

139. 单词拆分

题目描述

给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:

  • 拆分时可以重复使用字典中的单词。
  • 你可以假设字典中没有重复的单词。

力扣题目链接

139. 单词拆分

解题思路

这个问题可以使用动态规划来解决。我们定义一个布尔数组 valid,其中 valid[i] 表示字符串 s 的前 i 个字符是否可以由字典中的单词组成。

  1. 初始化 valid[0]true,因为一个空字符串总是可以被拆分(不需要任何单词)。
  2. 遍历字符串 s 的每一个位置 i,对于每一个位置,我们再遍历它的每一个可能的前缀 j
  3. 如果 s.substring(j, i) 是字典中的一个单词,并且 valid[j]true,那么我们可以说 s.substring(0, i) 也可以被拆分,因此我们将 valid[i] 设置为 true
  4. 最后,valid[s.length()] 将告诉我们整个字符串 s 是否可以被拆分。

代码实现

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        HashSet<String> set = new HashSet<>(wordDict);
        boolean[] valid = new boolean[s.length() + 1];
        valid[0] = true;
        for (int i = 1; i <= s.length(); i++) {
            for (int j = 0; j < i && !valid[i]; j++) {
                if (set.contains(s.substring(j, i)) && valid[j]) {
                    valid[i] = true;
                }
            }
        }
        return valid[s.length()];
    }
}

56. 携带矿石资源(第八期模拟笔试)

题目描述

你是一名宇航员,即将前往一个遥远的行星。在这个行星上,有许多不同类型的矿石资源,每种矿石都有不同的重要性和价值。你需要选择哪些矿石带回地球,但你的宇航舱有一定的容量限制。

给定一个宇航舱,最大容量为 C。现在有 N 种不同类型的矿石,每种矿石有一个重量 w[i],一个价值 v[i],以及最多 k[i] 个可用。不同类型的矿石在地球上的市场价值不同。你需要计算如何在不超过宇航舱容量的情况下,最大化你所能获取的总价值。

输入描述

输入共包括四行,第一行包含两个整数 C 和 N,分别表示宇航舱的容量和矿石的种类数量。

接下来的三行,每行包含 N 个正整数。具体如下:

  • 第二行包含 N 个整数,表示 N 种矿石的重量。
  • 第三行包含 N 个整数,表示 N 种矿石的价格。
  • 第四行包含 N 个整数,表示 N 种矿石的可用数量上限。

解题思路

这个问题是一个典型的多重背包问题,可以通过动态规划来解决。我们可以使用一个一维数组 dp 来表示在不同容量下的最大价值。数组的索引表示当前背包的容量,而值表示在该容量下能够获得的最大价值。

  1. 初始化 dp 数组,所有值设为 0,因为开始时背包中没有物品,价值为 0。
  2. 遍历每一种矿石,对于每一种矿石,再遍历其数量上限。
  3. 对于每一种数量,使用完全背包的思路,更新 dp 数组。
  4. 最后,dp[bagWeight] 将包含最大价值。

代码实现

import java.util.Scanner;
class multi_pack{
    public static void main(String [] args) {
        Scanner sc = new Scanner(System.in);

        int bagWeight, n;
        
        bagWeight = sc.nextInt();
        n = sc.nextInt();
        int[] weight = new int[n];
        int[] value = new int[n];
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) weight[i] = sc.nextInt();
        for (int i = 0; i < n; i++) value[i] = sc.nextInt();
        for (int i = 0; i < n; i++) nums[i] = sc.nextInt();

        int[] dp = new int[bagWeight + 1];

        for (int i = 0; i < n; i++) {
            for (int j = bagWeight; j >= weight[i]; j--) {
                for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) {
                    dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);
                }
            }
        }
        System.out.println(dp[bagWeight]);
    }
}

相关文章:

  • 布隆过滤器:一种简单而高效的集合查询方法
  • git中,如何查看具体单个文件的log
  • 3dtiles平移旋转工具制作
  • 今日运维之-Mac笔记本python环境问题
  • FFmpeg视频处理入门级教程
  • 汇编语言 第九章-转移指令的原理
  • Python GUI
  • OpenCV给图像添加噪声
  • 每日一题之铠甲合体
  • 代码随想录day21
  • 哈希表的复习
  • 25全国各省自考报名时间汇总⏰照片要求✅
  • 【附源码】基于opencv+pyqt5搭建的人脸识别系统
  • Golang 构建学习
  • 涉密载体管控系统革新:RFID技术引领,信息安全新境界
  • 《全星质量管理 QMS 软件系统》:赋能企业高效质量管理
  • javascript如何通过原型链实现对象的继承,并指出这种继承方式的优缺点
  • ViT 模型介绍(三)——简单实战项目
  • ctfshow做题笔记—栈溢出—pwn57~pwn60
  • 【硬件设计】DDR与HBM的功能、区别及未来发展分析
  • 工程院院士、武汉纺织大学校长徐卫林拟任湖北省属本科高校党委书记
  • 2025年新季夏粮收购量将达到2000亿斤左右
  • 特朗普亲家有了新工作:美国驻法大使
  • 韦尔股份拟更名豪威集团:更全面体现公司产业布局,准确反映未来战略发展方向
  • 去年中企海外新增风电装机量5.4GW,亚太区域占比过半
  • 海南保亭警方通报“两飞车党紧追女童”:两名初中生认错道歉