动态规划问题——换钱的方法数

news2024/11/24 20:31:50

题目:

给定数组arr,arr中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,代表要找的钱数,求换钱有多少种方法。

举例:

arr = [5, 10, 25, 1]  aim=0 

组成0元的方法有一种,就是所有面值的货币都不用,返回1

arr = [5, 10, 25, 1] aim=15

有6种,3*5,10+5,10+5*1,10*1+5,2*5+5*1,15*1,返回6

方法一:暴力递归

 代码实现:

    public static int coins1(int[] arr,int aim) {
        if (arr == null || arr.length == 0 || aim < 0) {
            return -1;
        }
        return process1(arr,0,aim);
    }
    //用 arr[index]的面值组成aim,返回总的方法数
    public static int process1(int[] arr,int index, int aim) {
        int res = 0;
        //当没有可用面值的时候 判断此时aim是否为0,如果为0的话,返回1,如果不为0,没有可以组成不为0的方法,返回0
        if (index == arr.length) {
            res = aim == 0 ? 1 : 0;
        } else {
            for (int k = 0; k * arr[index] <= aim; k++) {
                res += process1(arr,index+1,aim-k*arr[index]);
            }
        }
        return res;
    }

方法二:使用记忆搜索方法优化暴力递归:

对于arr=[5,10,25,1] aim=1000

当使用0张5元+1张十元,或者使用2张5元+0张十元,他们都会去递归 process1(arr,2,990)

在暴力递归方法中存在重复计算的问题

现在使用一个map来存放之前递归求得的值,在后面递归的时候先去map里面查

代码实现:

    public static int coins2(int[] arr, int aim) {
        if (arr == null || arr.length == 0 || aim < 0) {
            return -1;
        }
        int[][] map = new int[arr.length+1][aim+1];
        return process2(arr,0,aim,map);
    }
    public static int process2(int[] arr, int index, int aim, int[][] map) {
        int res = 0;
        if (index == arr.length) {
            res = aim == 0 ? 1 : 0;
        } else {
            int mapValue = 0;
            for (int k = 0; k * arr[index] <= aim; k++) {
                //从map里拿值,判断之前这个递归过程是否重复计算过
                mapValue = map[index+1][aim-arr[index]*k];
                if (mapValue != 0) {
                    res += mapValue == -1 ? 0 : mapValue;
                //如果该递归过程没有计算过,就正常计算
                }else {
                    res += process2(arr, index+1, aim - arr[index] * k, map);
                }
            }
        }
        //将结果存入map
        map[index][aim] = res == 0 ? -1 : res;
        return res;
    }

方法三:使用动态规划进行优化:

    public static int coins3(int[] arr, int aim) {
        if (arr == null || arr.length == 0 || aim < 0 ) {
            return 0;
        }
        int[][] dp = new int[arr.length][aim+1];
        //将第一列初始化为1
        for (int i = 0; i < arr.length; i++) {
            dp[i][0] = 1;
        }
        //初始化第一行
        for (int j = 1; arr[0] * j <= aim; j++) {
            dp[0][arr[0]*j] = 1;
        }
        int num = 0;
        for (int i = 1; i <arr.length; i++) {
            for(int j = 1; j <= aim; j++) {
                num = 0;
                for (int k = 0; j - arr[i]*k >= 0; k++) {
                    num += dp[i-1][j-arr[i] * k];
                }
                dp[i][j] = num;
            }
        }
        return dp[arr.length-1][aim];
    }

继续优化:

对于上述优化,计算其他 dp[i][j] 位置的时候,其实可以进一步优化:

dp[i][j] = dp[i-1][j] + dp[i][j-arr[i]]

dp[1][5]的含义:使用5元和10元组成5的方法数,只有1种;

dp[1][5] = dp[0][5] + dp[1][5-10] = 1+0 = 1 

dp[1][10]的含义:使用5元和10元组成10的方法数,有两种

dp[1][10] = dp[0][10] + dp[1][10-10] = 1+1 = 2

    public static int coins4(int[] arr, int aim) {
        if (arr == null || arr.length == 0 || aim < 0 ) {
            return 0;
        }
        int[][] dp = new int[arr.length][aim+1];
        //将第一列初始化为1
        for (int i = 0; i < arr.length; i++) {
            dp[i][0] = 1;
        }
        //初始化第一行
        for (int j = 1; arr[0] * j <= aim; j++) {
            dp[0][arr[0] * j] = 1;
        }
        for (int i = 1; i < arr.length; i++) {
            for (int j = 1; j <= aim; j++) {
                dp[i][j] = dp[i-1][j];
                dp[i][j] += j - arr[i] >= 0 ? dp[i][j-arr[i]] : 0;
            }
        }
        return dp[arr.length-1][aim];
    }

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

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

相关文章

【PCL1.11.0+win10+vs2019】环境配置/ 点云格式转换及可视化

文章目录一、安装1.1 下载PCL1.2 安装PCL1.3 安装OSGeo4W二、配置2.1 配置环境变量2.2 配置VS2019三、点云格式转换以及可视化参考一、安装 1.1 下载PCL 首先我们需要下载pcl1.11.0 &#xff0c;这个版本与vs2019对应。 有两种下载方法&#xff1a;百度网盘、官网下载。二选一…

docker原理及服务编排

一、什么是docker Docker 是一个开源项目&#xff0c;诞生于2013年初&#xff0c;最初是dotCloud公司内部的一个业余项目。它基于Google公司推出的Go语言实现。项目后来加入了Linux基金会&#xff0c;遵从了Apache 2.0协议&#xff0c;项目代码在GitHub上进行维护。 Docker 项…

【毕业设计_课程设计】基于Spark网易云音乐数据分析

文章目录0 项目说明1 系统模块2 分析内容3 界面展示4 项目工程0 项目说明 基于Spark网易云音乐数据分析 提示&#xff1a;适合用于课程设计或毕业设计&#xff0c;工作量达标&#xff0c;源码开放 1 系统模块 包含爬虫,Scala代码,Spark,Hadoop,ElasticSearch,logstash,Flume…

基于ChatGPT实现微信智能机器人

ChatGPT近期以强大的对话和信息整合能力风靡全网&#xff0c;可以写代码、改论文、讲故事&#xff0c;几乎无所不能&#xff0c;这让人不禁有个大胆的想法&#xff0c;能否用他的对话模型把我们的微信打造成一个智能机器人&#xff0c;可以在与好友对话中给出意想不到的回应&am…

汇编语言笔记——接口技术与编程

文章目录传送门储存系统与技术材料高速储存器缓冲储存器&#xff08;Cache&#xff09;材料&#xff0c;局部性&#xff0c;访问方式Cache全相联映射Cache交换与一致性单核CPU一致性处理多核CPU的MESI协议主储存器&#xff08;内存&#xff09;主要技术指标容量带宽内存模组与内…

【JavaWeb】Servlet

Servlet简介 Servlet是sun公司开发动态web的一门技术Sun在这些API中提供一个接口叫做&#xff1a;Servlet&#xff0c;如果想开发一个Servlet程序&#xff0c;需要编写一个类&#xff0c;实现Servlet接口把开发好的Java类部署到web服务器中 把实现了Servlet接口的Java程序叫做…

【Anime.js】——Anime.js源码核心理解

一、Anime.js整体结构 Anime.js的强大之处在于代码量非常少&#xff0c;但功能却非常强大。让我们一起来探索Anime.js源码的核心吧~ Anime.js之所以能如此强大主要是因为它的代码结构设计的非常巧妙合理&#xff0c;所以我们想要掌握Anime.js的核心&#xff0c;首先我们要了解…

Linux内核基础篇——动态输出调试

文章目录配置内核编译选项debugfs文件系统挂载动态输出使用实际案例动态输出&#xff08;dynamic print&#xff09;是内核子系统开发者最喜欢的输出技术之一。 上篇说到printk调试&#xff0c;但printk是全局的&#xff0c;只能设置输出等级。而动态输出可以动态选择打开某个…

Tensorflow Serving部署推荐模型

Tensorflow Serving部署推荐模型 1、找到当前模型中定义的variables&#xff0c;并在此定义一个saver用于保存模型参数 def saveVariables(self):variables_dict {}variables_dict[self.user_embedding.op.name] self.user_embeddingvariables_dict[self.item_embedding.op…

【LeetCode】1971. 寻找图中是否存在路径

题目描述 有一个具有 n 个顶点的 双向 图&#xff0c;其中每个顶点标记从 0 到 n - 1&#xff08;包含 0 和 n - 1&#xff09;。图中的边用一个二维整数数组 edges 表示&#xff0c;其中 edges[i] [ui, vi] 表示顶点 ui 和顶点 vi 之间的双向边。 每个顶点对由 最多一条 边连…

犀牛插件开发-基础核心-技术概览-总体架构-教程

文章目录1.概述2.基础核心2.1.C Rhino 核心2.2.openNURBS2.3.C SDK3.C Stack3.1.C Plugins3.2.RhinoScript4.NET Stack4.1.C API4.2.NET Framework4.3.RhinoCommon4.4.Eto4.5.net插件4.6.Grasshopper组件4.7.Python脚本5.相关主题1.概述 《Rhinoceros》由许多层组成——用多种…

细说OA系统的繁荣发展

改革开放以来&#xff0c;科技发展突飞猛进&#xff0c;我们生活的方方面面都受到了巨大影响。随着信息化时代的到来&#xff0c;企业的办公方式也发生了巨大的改变&#xff0c;OA系统随之走进了大众的视野。细数这四十几年&#xff0c;OA办公系统已经由一个异想天开的想法变成…

centos7.8离线安装pg和postgis

安装包下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1MxJc-5Ws6OPTRAoC-2srJw 提取码&#xff1a;is2q 1.centos7.8 离线安装pg操作步骤 这里基于centos7.8空白系统操作实践写的文档&#xff0c;系统一致的情况下可以照搬教程操作安装&#xff0c;镜像为…

1.0、Hibernate-快速入门初体验

1.0、Hibernate-快速入门初体验 Hibernate 和 mybatis 一样是 ORM (Object Relation Mapping) 对象关系映射框架&#xff0c;将面向对象映射成面向关系。 如何使用呢&#xff1f; 1、导入依赖&#xff1b; 2、创建 Hibernate 配置文件&#xff1b; 3、创建实体类&#xff1b; 4…

Allegro172版本多人协同在线设计操作指导

Allegro172版本多人协同在线设计操作指导 Allegro升级到172版本,可以支持多人协同设计,并且实时同步,具体操作如下 首先用户需要在同一个局域网下,并且Allegro172的版本必须一致,比如都是S082的版本 第一个用户打开PCB,选择Symphony Team design 选择 Start Symphony …

2022年度总结

自我介绍 大家好&#xff0c;我又回来了&#xff01;我在一年之前在 CSDN 写了第一篇文章&#xff0c;到现在也有一年时间了。这次回来呢&#xff0c;也是因为 CSDN 官方发的消息&#xff0c;让写一篇年度总结的文章。在离开的这几个月里&#xff0c;主要是因为工作繁忙&#…

ASO优化:总结APP被下架的5点原因

随着苹果的App Store的监管力度的不断加强&#xff0c;每个APP都会有被下架的风险&#xff0c;而对于开发者来说&#xff0c;APP被下架是一件很严重的事情&#xff0c;不仅会造成用户的流失&#xff0c;还会降低用户对APP 的信任。所以&#xff0c;我们要了解APP被下架的原因&a…

【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)

需要源码和依赖请点赞关注收藏后评论区留言私信~~~ 一、Dataframe操作 步骤如下 1&#xff09;利用IntelliJ IDEA新建一个maven工程&#xff0c;界面如下 2&#xff09;修改pom.XML添加相关依赖包 3&#xff09;在工程名处点右键&#xff0c;选择Open Module Settings 4&a…

整数的大小端序

在存储整数时&#xff0c;一般按字节为逻辑单位进行存储&#xff0c;有“小端序”和“大端序”之分。小端序&#xff08;little-endian&#xff09; 是指将表示整数的低位字节存储在内存地址的低位&#xff0c;高位字节存储在内存地址的高位。如果将整数 1982062410 存储至内存…

【CANN训练营第三季】2022年度第三季新手班之昇腾AI入门课

本次参加CANN训练营&#xff0c;本来我报名的是进阶班课程&#xff0c;再看一遍新手班&#xff0c;学习一下目前CANN的最新进展也是不错的&#xff0c;巩固一下。 视频课程大家可以从这里看到 &#xff08;1&#xff09;【CANN训练营第三季】- 昇腾AI入门课&#xff08;上&am…