代码随想录-Day43

news2024/12/23 11:03:06

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

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的重量,并且具有不同的价值。

小明的行李箱所能承担的总重量为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料可以选择无数次,并且可以重复选择。

输入描述
第一行包含两个整数,N,V,分别表示研究材料的种类和行李空间

接下来包含 N 行,每行两个整数 wi 和 vi,代表第 i 种研究材料的重量和价值

输出描述
输出一个整数,表示最大价值。
输入示例
4 5
1 2
2 4
3 4
4 5
输出示例
10
在这里插入图片描述
在这里插入图片描述

方法一:

//先遍历物品,再遍历背包
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 + "   ");
    }
}

这段代码是一个使用动态规划解决0-1背包问题的Java示例。0-1背包问题是指有N件物品和一个容量为W的背包,每种物品都有自己的重量和价值,在不超过背包所能装载的总重量的前提下,如何选择装入背包的物品,使得背包中物品的总价值最大。

代码解释如下:

  1. 定义了物品的重量数组 weight 和价值数组 value,以及背包的最大容量 bagWeight
  2. 创建一个数组 dp,长度为 bagWeight + 1,用于存储每个背包容量下的最大价值。初始化时,默认值都为0,表示背包为空时的价值为0。
  3. 外层循环(for (int i = 0; i < weight.length; i++))遍历每一件物品。
  4. 内层循环(for (int j = weight[i]; j <= bagWeight; j++))遍历从当前物品的重量开始到背包最大容量的所有可能的背包容量。这样设置是因为如果背包容量小于当前物品的重量,这件物品不可能被放入背包中,所以不必考虑。
  5. 在内层循环中,使用 Math.max() 函数比较两种情况:一是不把当前物品放入背包中时的最大价值 dp[j],二是把当前物品放入背包后剩余空间的最大价值 dp[j - weight[i]] + value[i],取两者的较大值作为新的 dp[j],即更新这个背包容量下的最大价值。
  6. 最后,通过遍历并打印数组 dp,可以得到不同背包容量下能够达到的最大价值。

这段代码执行后,会输出一个序列,表示从容量为0到容量为bagWeight的背包能够装入物品的最大价值。最后一项即为给定背包容量下的最大价值。

方法二:

//先遍历背包,再遍历物品
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 + "   ");
    }
}

这段代码同样是解决0-1背包问题的Java实现,但它的遍历顺序与上一个示例相反:首先遍历背包的容量,然后遍历物品。下面是这段代码的解释:

  1. 定义变量:与前一个示例相同,定义了物品的重量数组 weight、价值数组 value 以及背包的最大容量 bagWeight。同时初始化了一个 dp 数组来记录不同背包容量下的最大价值。

  2. 外层循环 (for (int i = 1; i <= bagWeight; i++)):这次是先从背包容量为1开始,直到遍历到最大背包容量 bagWeight。这里从1开始是因为容量为0的情况在初始化时已经设定为0,无需处理。

  3. 内层循环 (for (int j = 0; j < weight.length; j++)):遍历每一个物品。与前一个示例的遍历顺序相反。

  4. 条件判断 (if (i - weight[j] >= 0)):在尝试将当前物品放入背包之前,先检查当前背包的容量 i 是否至少能放下物品 j。这是必要的,因为如果背包容量不足以容纳当前物品,就无需继续计算加入该物品后的价值,直接跳过。

  5. 价值更新:如果背包容量足够,使用 Math.max() 函数比较当前背包容量下的最大价值 dp[i] 和将当前物品放入背包后剩余空间的最大价值加上当前物品的价值 dp[i - weight[j]] + value[j],取较大者作为新的 dp[i]。这一步确保了在考虑添加新物品时,背包的价值总是尽可能大。

  6. 输出结果:最后,遍历并打印数组 dp,展示不同背包容量下可达到的最大价值。最后一项依然是整个问题的解,即背包最大容量为 bagWeight 时能够装入物品的最大总价值。

这种遍历顺序(先背包容量,后物品)也是解决0-1背包问题的有效方法,它在逻辑上直观地体现了“逐渐增加背包容量并尝试放入所有物品以最大化价值”的过程。

518. 零钱兑换 II

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

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

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

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

示例 1:

输入:amount = 5, coins = [1, 2, 5]
输出:4
解释:有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
示例 2:

输入:amount = 3, coins = [2]
输出:0
解释:只用面额 2 的硬币不能凑成总金额 3 。
示例 3:

输入:amount = 10, coins = [10]
输出:1
在这里插入图片描述

方法一:

class Solution {
    public int change(int amount, int[] coins) {
        //递推表达式
        int[] dp = new int[amount + 1];
        //初始化dp数组,表示金额为0时只有一种情况,也就是什么都不装
        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];
    }
}

这段代码是Java语言实现的一个解决方案,解决的是找零问题(Coin Change Problem)。给定一定数量的硬币(每种硬币的数量不限)和一个总金额,求出有多少种不同的组合方式可以凑成总金额。这是一个经典的动态规划问题。

具体分析如下:

  1. 定义状态dp[j] 表示总额为 j 时的找零方案数。这是我们要填充的动态规划数组。

  2. 初始化dp[0] = 1,表示当金额为0时,有一种组合方式(即不选任何硬币)。

  3. 双层循环

    • 外层循环 for (int i = 0; i < coins.length; i++) 遍历每一种硬币。
    • 内层循环 for (int j = coins[i]; j <= amount; j++) 从当前硬币的面值开始,遍历到总金额。这是因为如果当前金额小于硬币的面值,不可能再用这个硬币去凑更小的金额,所以从硬币面值开始是有意义的起始点。
  4. 状态转移方程dp[j] += dp[j - coins[i]]。对于每一个 j,都有两种情况:要么使用当前硬币 coins[i],那么剩余的金额就是 j - coins[i],方案数就是 dp[j - coins[i]];要么不使用当前硬币,直接继承之前的方案数 dp[j]。但因为我们要累加所有可能的组合,所以是累加而不是直接赋值。

  5. 返回结果:最后返回 dp[amount],即为目标总金额的找零方案数。

综上所述,这段代码通过动态规划的方法,高效地计算出了给定硬币种类和总金额下的找零组合数。

方法二:

// 二维dp数组版本,方便理解
class Solution {
    public int change(int amount, int[] coins) {
        int[][] dp = new int[coins.length][amount+1];

        // 初始化边界值
        for(int i = 0; i < coins.length; i++){
            // 第一列的初始值为1
            dp[i][0] = 1;
        }
        for(int j = coins[0]; j <= amount; j++){
            // 初始化第一行
            dp[0][j] += dp[0][j-coins[0]];
        }
        
        for(int i = 1; i < coins.length; i++){
            for(int j = 1; j <= amount; j++){
                if(j < coins[i]) dp[i][j] = dp[i-1][j];
                else dp[i][j] = dp[i][j-coins[i]] + dp[i-1][j];
            }
        }

        return dp[coins.length-1][amount];
    }
}

这段代码是另一个版本的解决方案,同样用来解决找零问题(Coin Change Problem),但是使用了二维动态规划数组来实现,这有助于更直观地理解动态规划的状态转移过程。下面是对代码的详细解析:

  1. 初始化二维dp数组int[][] dp = new int[coins.length][amount+1];,其中 dp[i][j] 表示在前 i+1 种硬币中选取,凑成总额为 j 的组合数。

  2. 初始化边界值

    • 对于每一行(每种硬币)的首列(总额为0的情况),都只有1种方法,即不选择任何硬币,因此 dp[i][0] = 1;
    • 初始化第一行时,需要根据第一种硬币的不同面额来填充。对于每一列 j(从硬币面值开始到总金额),如果可以由若干个第一种硬币组成,即 j >= coins[0],则 dp[0][j] += dp[0][j-coins[0]],意味着可以通过在已有的组合基础上再添加一个硬币来得到这个总额。
  3. 状态转移:核心的双层循环遍历每一种硬币和每一个可能的总金额。

    • 对于 i > 0(即除了第一种硬币之外的其他硬币)和 j > 0(即除了总额为0之外的情况),有两种选择:
      • 不使用第 i 种硬币,这时的组合数与前 i-1 种硬币凑成总额 j 的组合数相同,即 dp[i][j] = dp[i-1][j]
      • 使用至少一个第 i 种硬币,剩余的金额为 j - coins[i],这时的组合数是在总额减去当前硬币面值后,使用全部 i 种硬币的组合数,即 dp[i][j-coins[i]]。因此,这两种情况的组合数相加即为最终的 dp[i][j]
      • 注意,当 j < coins[i],即当前总额无法再使用第 i 种硬币时,不应考虑使用该硬币的情况,直接继承前 i-1 种硬币的结果。
  4. 返回结果:最终答案为 dp[coins.length-1][amount],即在所有硬币中选择,凑成总金额为 amount 的所有可能组合数。

这个版本虽然占用更多的空间,但它清晰地展现了每一步决策的过程,便于理解和分析动态规划的状态转移逻辑。

377. 组合总和 Ⅳ

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

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

示例 1:

输入:nums = [1,2,3], target = 4
输出:7
解释:
所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
请注意,顺序不同的序列被视作不同的组合。
示例 2:

输入:nums = [9], target = 3
输出:0
在这里插入图片描述

class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target + 1];
        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];
    }
}

这段代码是用来解决完全背包问题(Unbounded Knapsack Problem)的一个变种——求解组合总和IV的问题。给定一个由正整数组成的数组 nums 和一个目标整数 target,找出并返回可以由 nums 中的数字组成的、和为目标整数 target 的不同非空组合的数量。每个数组中的数字可以无限制次数地重复被选取。

这里是使用一维动态规划的解决方案,具体解析如下:

  1. 初始化dp数组int[] dp = new int[target + 1];,其中 dp[i] 表示总和为 i 的组合数。初始化 dp[0] = 1,表示总和为0的情况只有一个组合(即不选任何数)。

  2. 双层循环

    • 外层循环 for (int i = 0; i <= target; i++) 遍历从0到目标值 target 的每一个可能的总和。
    • 内层循环 for (int j = 0; j < nums.length; j++) 遍历数组 nums 中的所有数字。
  3. 状态转移:对于每个总和 i,考虑数组中的每个数 nums[j],如果当前总和 i 大于等于这个数(i >= nums[j]),说明可以使用 nums[j] 来构成总和 i 的一部分,那么 dp[i] 应该加上总和为 i - nums[j] 时的组合数,即 dp[i] += dp[i - nums[j]]。这样就实现了从已知的较小问题的解来构建更大问题解的过程。

  4. 返回结果:最终答案是 dp[target],即所有元素和为目标值 target 的组合总数。

这个解法有效地利用了动态规划避免了重复计算,降低了时间复杂度。其时间复杂度大致为O(n * target),其中n为数组 nums 的长度,target为所求的目标和。

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

题目描述
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

输入描述
输入共一行,包含两个正整数,分别表示n, m
输出描述
输出一个整数,表示爬到楼顶的方法数。
输入示例
3 2
输出示例
3

import java.util.Scanner;
class climbStairs{
    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]);
        }
    }
}

这段Java代码实现了一个爬楼梯问题的解法,不过这里的描述有误,实际上解决的是完全背包问题的一个变形,而非直接的爬楼梯问题。但我们可以按照代码逻辑来理解它所解决的问题:给定一个人可以一次跳跃1到m个台阶,问他有多少种不同的方式跳上n阶楼梯。

解析如下:

  1. 导入Scanner类:用于从控制台读取用户输入的数据。
  2. 定义主函数:在主函数中,程序通过Scanner对象sc读取两个整数,分别代表楼梯阶数n和每次跳跃的最大阶数m
  3. 初始化动态规划数组:创建一个大小为n+1的数组dp,其中dp[j]表示到达第j阶楼梯的不同方法数。初始化dp[0]=1,表示站在起点(0阶)只有1种方法(即不跳)。
  4. 双层循环
    • 外层循环for (int j = 1; j <= n; j++)遍历从第1阶到第n阶楼梯。
    • 内层循环for (int i = 1; i <= m; i++)遍历每次跳跃的阶数,从1跳到m。
    • 如果当前阶数j大于或等于跳跃的阶数i,则可以从j-i阶跳到第j阶,因此dp[j]需要累加dp[j-i],即之前阶数到达方式的总数。
  5. 输出结果:最后,输出dp[n],即到达第n阶楼梯的所有不同方法数。

尽管注释提到“求排列问题,先遍历背包再遍历物品”,但实际上这段代码解决的是一个组合问题,更准确地说是完全背包问题的一种特殊情况,用来计算在给定步长限制下到达特定楼层的方案数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1877294.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[OtterCTF 2018]Recovery

里克必须找回他的文件&#xff01;用于加密文件的随机密码是什么 恢复他的文件 &#xff0c;感染的文件 &#xff1f; vmware-tray.ex 前面导出的3720.dmp 查找一下 搜索主机 strings -e l 3720.dmp | grep “WIN-LO6FAF3DTFE” 主机名 后面跟着一串 代码 aDOBofVYUNVnmp7 是不…

c++类和对象(三)日期类

类和对象 一.拷贝构造函数定义二.拷贝构造函数特征三.const成员函数权限权限的缩小权限的缩放大 四.隐式类型转换 一.拷贝构造函数定义 拷贝构造函数&#xff1a;只有单个形参&#xff0c;该形参是对本类类型对象的引用(一般常用const修饰)&#xff0c;在用已存 在的类类型对象…

韩顺平0基础学Java——第33天

p653-674 坦克大战 继续上回游戏 将每个敌人的信息&#xff0c;恢复成Node对象&#xff0c;放进Vector里面。 播放音乐 使用一个播放音乐的类。 第二阶段结束了 网络编程 相关概念 &#xff08;权当是复习计网了&#xff09; 网络 1.概念:两台或多台设备通过一定物理设备连…

Java基础知识-集合类

1、HashMap 和 Hashtable 的区别&#xff1f; HashMap 和 Hashtable是Map接口的实现类&#xff0c;它们大体有一下几个区别&#xff1a; 1. 继承的父类不同。HashMap是继承自AbstractMap类&#xff0c;而HashTable是继承自Dictionary类。 2. 线程安全性不同。Hashtable 中的方…

【Nginx】源码安装

nginx官网&#xff1a;nginx: download 选择文档版本安装即可 1.安装依赖包 //一键安装上面四个依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 2.下载并解压安装包 //创建一个文件夹 cd /usr/local mkdir nginx cd nginx //将下载的nginx压缩…

蓝卓出席“2024C?O大会”,探讨智能工厂建设新路径

6月29日&#xff0c;“2024C?O大会”在金华成功举办。此次大会由浙江省企业信息化促进会主办&#xff0c;与以往CIO峰会不同&#xff0c;“C?O”代表了企业数字化中的核心决策者群体&#xff0c;包括传统的CIO、CEO、CDO等。 本次大会围绕C?O、AIGC与制造业、数据价值、未来…

MySQL之可扩展性(九)

可扩展性 直接连接 2.修改应用的配置 还有一个分发负载的办法是重新配置应用。例如&#xff0c;你可以配置多个机器来分担生成大报表操作的负载。每台机器可以配置成连接到不同的MySQL备库&#xff0c;并为第N个用户或网站生成报表。 这样的系统很容易实现&#xff0c;但如果…

第7章_低成本 Modbus 传感器的实现

文章目录 第7章 低成本 Modbus 传感器的实现7.1 硬件资源介绍与接线7.2 开发环境搭建7.3 创建与体验第 1 个工程7.3.1 创建工程7.3.2 配置调试器7.3.3 配置 GPIO 操作 LED 7.4 UART 编程7.4.1 使用 STM32CubeMX 进行配置1.UART12.配置 RS485方向引脚 7.4.2 封装 UART7.4.3 上机…

memory动态内存管理学习之weak_ptr

此头文件是动态内存管理库的一部分。std::weak_ptr 是一种智能指针&#xff0c;它持有对被 std::shared_ptr 管理的对象的非拥有性&#xff08;“弱”&#xff09;引用。在访问所引用的对象前必须先转换为 std::shared_ptr。std::weak_ptr 用来表达临时所有权的概念&#xff1a…

快速应用开发(RAD):加速软件开发的关键方法

目录 前言1. 快速应用开发的概念1.1 什么是快速应用开发&#xff1f;1.2 RAD与传统开发方法的对比 2. 快速应用开发的实施步骤2.1 需求分析与规划2.2 快速原型开发2.3 用户评估与反馈2.4 迭代开发与改进2.5 最终交付与维护 3. 快速应用开发的优点与应用场景3.1 优点3.2 应用场景…

24级中国科学技术大学843信号与系统考研分数线,中科大843初复试科目,参考书,大纲,真题,苏医工生医电子信息与通信工程。

(上岸难度&#xff1a;★★★★☆&#xff0c;考试大纲、真题、经验帖等考研资讯和资源加群960507167/博睿泽电子信息通信考研咨询&#xff1a;34342183) 一、专业目录及考情分析 说明: ①复试成绩:满分100分。上机满分50分&#xff0c;面试满分150分&#xff0c;复试成绩(上机…

Llama 3 模型微调的步骤

环境准备 操作系统&#xff1a;Ubuntu 22.04.5 LTS Anaconda3&#xff1a;Miniconda3-latest-Linux-x86_64 GPU&#xff1a; NVIDIA GeForce RTX 4090 24GStep 1. 准备conda环境 创建一个新的conda环境&#xff1a; conda create --name llama_factory python3.11激活刚刚创…

线性代数--行列式1

本篇来自对线性代数第一篇的行列式的一个总结。 主要是行列式中有些关键点和注意事项&#xff0c;便于之后的考研复习使用。 首先&#xff0c;对于普通的二阶和三阶行列式&#xff0c;我们可以直接对其进行拆开&#xff0c;展开。 而对于n阶行列式 其行列式的值等于它的任意…

系统运维面试题总结(网络基础类)

系统运维面试题总结&#xff08;网络基础类&#xff09; 网络基础类第七层&#xff1a;应用层第六层&#xff1a;表示层第五层&#xff1a;会话层第四层&#xff1a;传输层第三层&#xff1a;网络层第二层&#xff1a;数据链路层第一层&#xff1a;物理层 类似面试题1、TCP/IP四…

Django 配置静态文件

1&#xff0c;DebugTrue 调试模式 Test/Test/settings.py DEBUG True...STATICFILES_DIRS [os.path.join(BASE_DIR, static),] STATIC_URL /static/ 1.1 创建静态文件 Test/static/6/images/Sni1.png 1.2 添加视图函数 Test/app6/views.py from django.shortcuts impor…

使用Java实现通用树形结构转换工具类:深入解析TreeUtil和TreeNode接口

文章目录 一、TreeNode接口设计二、TreeUtil工具类设计三、示例&#xff1a;实现TreeNode接口的节点类四、示例&#xff1a;使用TreeUtil构建树形结构五、总结 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1…

落石滑坡监测报警系统:创新保障高速公路安全

​ ​​在现代交通建设中&#xff0c;高速公路的安全性和稳定性至关重要。特别是易发生落石区域&#xff0c;如何有效预防和应对落石滑坡带来的事故成为了一项关键性挑战。为此&#xff0c;落石滑坡监测报警系统应运而生&#xff0c;它通过先进的技术手段&#xff0c;为高速…

汇聚荣拼多多运营好吗?

在当前电商行业竞争激烈的背景下&#xff0c;拼多多凭借其独特的商业模式和市场定位迅速崛起&#xff0c;成为众多商家和品牌争相入驻的平台。对于“汇聚荣拼多多运营好吗?”这一问题&#xff0c;答案是肯定的。拼多多不仅提供了一个广阔的市场空间&#xff0c;还通过其创新的…

C++输出彩色方块

1.使用方法 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xab); ———————————————————————————————————————— 0 黑色 1 蓝色 2 绿色 3 湖蓝色 4 红色 5 紫色 6 黄色 7 白色 8 灰色 9 …

linux下安装kkFileView4

kkFileView为文件文档在线预览解决方案&#xff0c;该项目使用流行的spring boot搭建&#xff0c;易上手和部署&#xff0c;基本支持主流办公文档的在线预览&#xff0c;如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等 安装kkFileView前需要安装LibreOffic…