暴力递归转动态规划(十四)

news2024/11/26 13:32:44

题目
arr是面值数组,其中的值都是正数且没有重复。再给定一个正数aim。
每个值都认为是一种面值,且认为张数是无限的。
返回组成aim的最少货币数

暴力递归
依然是面值张数的问题,暴力递归尝试的过程是从数组arr index = 0位置出发,一直到 index = arr.length。如果能够正好凑齐aim,则return 0,否则 return Integer.Max_Value用来进行区分。
需要注意的是:因为是求最少货币数,所以需要通过数组中下一个面值的张数使用 + 当前面值的张数使用,取最小值

代码
如果index == arr.length时,没有面值可以取了,如果此时rest = 0,说明正好凑齐钱数,return 0,否则return MAX_VALUE代表搞不了。
next != MAX_VALUE,则说明使用下一张面值刚好可以凑整aim钱数,那么就用当前面值的张数 zhang + 下一张面值的张数 next,和ans取最小值。
所以要通过MAX_VALUE来进行区分。

public static int minCoins(int[] arr, int aim) {
        return process(0, arr, aim);
    }

    public static int process(int index, int[] arr, int rest) {
        if (index == arr.length) {
            return rest == 0 ? 0 : Integer.MAX_VALUE;
        } else {
            int ans = Integer.MAX_VALUE;
            for (int zhang = 0; zhang * arr[index] <= rest; zhang++) {
                //要去index + 1位置看下一张面值的钱的使用情况
                int next = process(index + 1, arr, rest - zhang * arr[index]);
                // 如果使用下一张面值 恰好可以将 rest凑齐
                if (next != Integer.MAX_VALUE) {
                    //则,将当前使用面值张数 + 下一张面值使用张数 与 ans取最小值
                    ans = Math.min(ans, next + zhang);
                }
            }
            return ans;
        
    }

动态规划
根据暴力递归的代码改写动态规划,可变参数为 剩余金额 rest 和 数组下标 index,因为 rest 可以到达0位置,index可以到达arr.length。所以可以确定dp[][]的大小是 的 dp[arr.length + 1 ][aim + 1]。
确定好dp表大小后,根据暴力递归中的base case来填充dp表的默认值。
可以看到。暴力递归代码中,当index == arr.length时, 如果此时剩余金额 rest = 0,则return 0 ,否则 return MAX_VALUE。又因为int型数组,创建后,每个格子默认值就是0,所以只需要将dp[arr.length][1 ~ aim]的位置填充即可。其余代码照抄,dp表就填充完成了。

代码
暴力递归代码中,每次都是依赖index + 1位置 rest - zhang * arr[index],所以外层循环从N -1向0处遍历, 内循环 rest从0 向aim处遍历。

  public static int dp(int[] arr, int aim) {
        int N = arr.length;
        int[][] dp = new int[N + 1][aim + 1];

        for (int rest = 1; rest <= aim;rest ++){
            dp[N][rest] = Integer.MAX_VALUE;
        }
        for (int index = N - 1; index >= 0; index--) {
            for (int rest = 0; rest <= aim; rest++) {
                int ans = Integer.MAX_VALUE;
                for (int zhang = 0; zhang * arr[index] <= rest; zhang++) {
                    int next = dp[index + 1][rest - zhang * arr[index]];
                    if (next != Integer.MAX_VALUE) {
                        ans = Math.min(ans, next + zhang);
                    }
                    dp[index][rest] = ans;
                }
            }
        }
        return dp[0][aim];
    }

再次优化
可以看到动态规划的代码中,每填充1个dp表中格子都有枚举行为(zhang的for循环)。所以还可以再次进行优化。找到dp表中的依赖关系,替换掉这个for循环即可。
找依赖关系最直观的方法就是画图。
假设当前我剩余钱数 = 11,面值为3。
在这里插入图片描述
根据暴力递归代码带入看一下,我依赖的a0 ~ d3,当前面值使用0张,1张。。。的各种情况向下递归。
那如果此时rest = 8,依赖的就是b1 ~ d3,不过此时使用的张数也是0张、1张。。。。以此类推。
所以想要求 √ 位置的值,就是 a0 + (x + 1)。
为什么要加1呢? 还是回到暴力递归中的代码来看 这行代码 ans = Math.min(ans, next + zhang);
如果我next有效,我用的是 next + zhang,是在我当前面值使用了1,2,3若干张之后的情况,所以x位置,也是 √ 使用的一张arr[index]后剩余的rest = 8。

代码
首先保证左侧有值,并且左侧的值是有效的才进行比较。

public static int bestDP(int[] arr, int aim) {
        int N = arr.length;
        int[][] dp = new int[N + 1][aim + 1];

        for (int rest = 1; rest <= aim;rest ++){
            dp[N][rest] = Integer.MAX_VALUE;
        }
        for (int index = N - 1; index >= 0; index--) {
            for (int rest = 0; rest <= aim; rest++) {
                dp[index][rest] = dp[index + 1][rest];
                if (rest - arr[index] >= 0 && dp[index][rest - arr[index]] != Integer.MAX_VALUE) {
                    dp[index][rest] = Math.min(dp[index][rest], dp[index][rest - arr[index]] + 1);
                }
            }
        }
        return dp[0][aim];
    }

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

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

相关文章

mongodb导出聚合查询的数据

❗️❗️❗️在正文之前先要讲一个坑&#xff0c;就是mongoexport这个命令工具不支持导出聚合查询的数据&#xff0c;比如通过某某字段来分组 我查了一天关于mongoexport怎么来导出聚合查询的结果集&#xff0c;最终还是gpt给了我答案 &#x1f62d; 既然mongoexport不支持&…

Postgresql数据类型-布尔类型

前面介绍了PostgreSQL支持的数字类型、字符类型、时间日期类型&#xff0c;这些数据类型是关系型数据库的常规数据类型&#xff0c;此外PostgreSQL还支持很多非常规数据类型&#xff0c;比如布尔类型、网络地址类型、数组类型、范围类型、json/jsonb类型等&#xff0c;从这一节…

微信的通讯录联系人,有没有什么办法导出来做备份

6-10 这是可以做到的&#xff0c;并且很简单&#xff0c;对于需要把微信通讯录备份出来&#xff0c;或者离职交接的人来说&#xff0c;本文非常适合阅读&#xff0c;只是一个简单的方法&#xff0c;即可快速地把微信的通讯录搞出来&#xff0c;本质其实就是使用正确的工具就行…

Capacitor 插件 实现本地通知 Local Notification @capacitor/local-notifications

Capacitor 插件 实现本地通知 Local Notification capacitor/local-notifications 在前一个文章中使用 Capacitor 和 H5 应用构建了一个 Android 应用&#xff0c;这个 h5 是通过 uniapp 生成的。 https://blog.csdn.net/KimBing/article/details/134093769 这个应用的构成是这…

微机原理3

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案。 1. 在机器数中&#xff0c;零的表示形式唯一的编码是() A. 原码 B. 补码 C.移码 D. 反码 2,用于定义常数、变量的内存空间分配和定位的是()。 A. 伪指令 B.机器指令…

(C++17) variant的使用与union对比

文章目录 前言与需求union内存映射图C11的union 使用ref示例构造普通构造置空emplacemonostate 访问std::get<>std::holds_alternative<>获取指针std::get_if<>获取可选数量个数std::variant_size END 前言与需求 联合体&#xff0c;是在C语言时代就存在的概…

『亚马逊云科技产品测评』活动征文|AWS 云服务器实例类型及其适用场景详细说明

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 目录 一、AWS 定价计算器 &#xff08;1&#xff09;定价计算器官网 &…

Linux环境配置(云服务器)

目录 1.第一步&#xff1a;购买云服务器 2.第二步&#xff1a;下载Xshell 7 3.第三步&#xff1a;打开Xshell&#xff0c;登录云服务器 4.第四步&#xff1a;更加便捷的云服务器登录方式 1.第一步&#xff1a;购买云服务器 &#xff08;推荐&#xff1a;阿里云、华为云、腾…

机器视觉工程师注意,没有经历过公司倒闭看下文章,机器视觉公司即将要倒闭的征兆是什么?

很多机器视觉工程师没有经历过公司倒闭&#xff0c;谁也不想自己的公司倒闭&#xff0c;毕竟我们是打工人&#xff0c;拿固定工资的。 机器视觉公司即将要倒闭的征兆有哪些迹象​&#xff1f;​ 1、PM&#xff0c;机器视觉工程师频繁开会&#xff0c;甚至周末强制开会。 2.停…

P6入门:项目初始化1-项目详情介绍

前言 使用项目详细信息查看和编辑有关所选项目的详细信息&#xff0c;在项目创建完成后&#xff0c;初始化项目是一项非常重要的工作&#xff0c;涉及需要设置的内容包括项目名&#xff0c;ID,责任人&#xff0c;日历&#xff0c;预算&#xff0c;资金&#xff0c;分类码等等&…

Zigbee—网络层地址分配机制

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;孤雏 0:21━━━━━━️&#x1f49f;──────── 4:14 &#x1f504; ◀️ ⏸ ▶️ ☰ &#x1f497;关注…

进行 “最佳价格查询器” 的开发

前置条件 public class Shop {private final String name;private final Random random;public Shop(String name) {this.name name;random new Random(name.charAt(0) * name.charAt(1) * name.charAt(2));}public double getPrice(String product) {return calculatePrice…

『 C++类与对象 』多继承与虚继承

文章目录 ⌨️多继承的概念语法 &#x1f5b1;️ ⌨️棱形继承⌨️虚继承虚继承是如何解决数据冗余和二义性的(不谈虚表概念)?&#x1f5b1;️ ⌨️多继承的概念 多继承指的是一个派生类是由多个基类继承而来的; 而在生活当中也有类似的例子:番茄既可以是水果,也可以是蔬菜;…

[100天算法】-面试题 17.11.单词距离(day 68)

题目描述 有个内含单词的超大文本文件&#xff0c;给定任意两个单词&#xff0c;找出在这个文件中这两个单词的最短距离(相隔单词数)。如果寻找过程在这个文件中会重复多次&#xff0c;而每次寻找的单词不同&#xff0c;你能对此优化吗?示例&#xff1a;输入&#xff1a;word…

华为Auth-Http Serve任意文件读取

1.漏洞描述 华为Auth-Http Server 1.0任意文件读取&#xff0c;攻击者可通过该漏洞读取任意文件。 2.网络资产查找 FOFA&#xff1a;server”Huawei Auth-Http Server 1.0” 2、部分界面如下 3、Poc /umweb/shadow 4、Poc批量验证 id: huanwei-auth-http-server-filereadi…

商业模式思维导图

一、什么是商业模式&#xff1f;简单的说&#xff0c;商业模式就是公司通过什么途径或方式来赚钱&#xff1f; 商业模式的核心是 创造价值-获取价值-传递价值。 它有3个重要的环节&#xff0c;创造价值是基于客户需求&#xff0c;提供解决方案&#xff0c;传递价值是通过资源配…

5个写自定义函数小练习

计算列表平均值、素数判定、反转字符串&#xff0c;查找整数列表最大最小值、统计字符串中元音字母个数(大小写字不敏感)。 (笔记模板由python脚本于2023年11月09日 21:50:35创建&#xff0c;本篇笔记适合熟悉Python函数及基本数据类型的coder翻阅) 【学习的细节是欢悦的历程】…

Python克隆单个网页

网上所有代码都无法完全克隆单个网页&#xff0c;不是Css&#xff0c;Js下载不下来就是下载下来也不能正常显示&#xff0c;只能自己写了&#xff0c;记得点赞~ 效果如图&#xff1a; 源码与所需的依赖&#xff1a; pip install requests pip install requests beautifulsoup4…

ThreadLocal原理以及内存泄露问题

1、ThreadLocal实现原理 1、每个线程中有一个ThreadLocalsMap&#xff0c;这是一个哈希表的结构里面有很多entry(也就是k-v)&#xff0c;当我们使用ThreadLocal进行set值的时候,会将这个threadLocal设置为key,然后值设置为value放入ThreadLocalsMap&#xff0c;key为弱引用&am…

Vue计算属性 computed

计算属性&#xff1a;常用于逻辑比较复杂的计算&#xff0c;根据已有的数据&#xff0c;计算出一个新的数据。计算属性具有缓存机制&#xff0c;复用性强&#xff0c;效率更高。 计算属性【简写方式】&#xff1a; <template><div>提现金额&#xff1a;<input …