凑硬币问题

假设有 1 元,3 元,5 元的硬币若干(无限),现在需要凑出 11 元,问如何组合才能使硬币的数量最少?

用数组d来存储当前每个面值可以对应的合成的最小数量

d(i) = d(j) + 1

这里 j < i。通俗地讲,我们需要凑出 i 元,就在凑出 j 的结果上再加上某一个硬币就行了。

那这里加上的哪个硬币呢。把每个硬币试一下就行了:

1.假设最后加上的是 1 元硬币,那 d(i) = d(j) + 1 = d(i - 1) + 1。

2.假设最后加上的是 3 元硬币,那 d(i) = d(j) + 1 = d(i - 3) + 1。

3.假设最后加上的是 5 元硬币,那 d(i) = d(j) + 1 = d(i - 5) + 1。

我们分别计算出 d(i - 1) + 1,d(i - 3) + 1,d(i - 5) + 1 的值,取其中的最小值,即为最优解,也就是 d(i)。

状态转移方程 d(i)=min{d(j)+1},if i>j

d(0)=0;

d(1)=1;

d(2)=d(1)+1=2;

d(3)=min{d(2)+1,d(0)+1}=1;

d(4)=min{d(3)+1,d(1)+1}=2;

d(5)=min{d(4)+1,d(2)+1,d(0)+1}=1;

d(6)=min{d(5)+1,d(3)+1,d(1)+1}=2;

public class test1430 {

private int[] d; // 储存结果

private int[] coins = {1,3,5}; // 硬币种类

private void d_func(int i, int num) {

if (i == 0) {

d[i] = 0;

d_func(i + 1, num);

}

else {

int min = 1000000; // 初始化一个很大的数值。当最后如果得出的结果是这个数时,说明凑不出来。

for (int coin : coins) {

if (i >= coin && d[i - coin] + 1 < min) {//比较得到最小值

min = d[i - coin] + 1;

}

}

d[i] = min;

if (i < num) {

d_func(i + 1, num);

}

}

}

@Test

public void test() throws Exception {

int sum = 11; // 需要凑 11 元

d = new int[sum + 1]; // 初始化数组

d_func(0, sum); // 计算需要凑出 0 ~ sum 元需要的硬币数量

for (int i = 0; i <= sum; i++) {

System.out.println("凑齐 " + i + " 元需要 " + d[i] + " 个硬币");

}

}

}

运行结果

当测试数据换成3、10、12.发现无法合成的数据也可以表示出来。因为其无法参与赋值,所以结果还是设置的Min=1000000

思考:如果要求得需要的最大硬币数 应该如何处理

这里花了我好久的时间 感觉自己真的是蠢 智商不够 想了一种方法 就是用t数组存最大数值,然后每次和max比较,将最大的留下。当然考虑到有的没办法获得,则没办法获得的赋值为0。结合前面的进行更改。写的不好,如果有好一点的方法希望能说一下。

private static int[] d; // 储存结果

private static int[] t;

private static int[] coins = {3,5,6}; // 硬币种类

private static void d_func_max(int i, int num) {

if (i == 0) {

d[i] = 0;

t[i]=0;

d_func_max(i + 1, num);

}

else {

int min = 1000000; // 初始化一个很大的数值。当最后如果得出的结果是这个数时,说明凑不出来。

for (int coin : coins) {

if (i >= coin && d[i - coin] + 1 < min) {

min = d[i - coin] + 1;

}

}

d[i] = min;

int max=0;

for (int coin : coins) {

if(d[i]==1000000){

break;

}

if (i >= coin && t[i - coin] + 1 > max) {

max = t[i - coin] + 1;

}

}

t[i]=max;

if (i < num) {

d_func_max(i + 1, num);

}

}

}

public static void main(String[] args){

int sum = 12; // 需要凑 11 元

d = new int[sum + 1]; // 初始化数组

t= new int[sum+1];

d_func_max(0, sum); // 计算需要凑出 0 ~ sum 元需要的硬币数量

for (int i = 0; i <= sum; i++) {

System.out.println("凑齐 " + i + " 元最多需要"+t[i] + " 个硬币");

}

}

}

测试数据3、5、6。结果如图

java动态规划凑硬币问题_动态规划 凑硬币问题相关推荐

  1. java实现多边形游戏问题_动态规划-多边形游戏

    算法思想:动态规划 实际问题:多边形游戏 编写语言:Java 前言 多边形游戏问题是矩阵连乘的最优计算次序问题与凸多边形最优三角剖分问题的推广.我在解决凸多边形最优三角剖分问题时偶然间看到了这个结论, ...

  2. 动态规划java实现数塔问题_动态规划入门_数塔问题

    在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少? 已经告诉你了,这是个DP的题目 ...

  3. java 动态规划找零钱_动态规划之找零钱问题

    找零钱是一个经典的动态规划问题.这种问题,我建议,首先学会暴力解法,然后从暴力解法中优化出动态规划的解法,这样,更能体会动态规划的魅力. 问题描述 有n种不同币值的硬币,硬币数量无限.给定一个数量T, ...

  4. java 最少货币单元组合换钱_动态规划. 换钱的最少货币数和最多方法数

    通过对换钱类题目的学习,我们将了解到 暴力递归及优化方法 记忆搜索(优化一) 动态规划的基本实现方法(优化二) 动态规划的空间优化(优化三) 1. 换钱的最少货币数,货币可重复使用 给定数组arr,a ...

  5. 变种 背包问题_动态规划入门——传说中的零一背包问题

    今天是周三算法与数据结构专题的第12篇文章,动态规划之零一背包问题.在之前的文章当中,我们一起探讨了二分.贪心.排序和搜索算法,今天我们来看另一个非常经典的算法--动态规划.在acm-icpc竞赛领域 ...

  6. sql表中只有子节点的递归_动态规划与静态规划、递归、分治、回溯

    动态规划算是运筹学或者算法中的硬骨头了.不是说算法本身有多难,而是学完用完之后还是感觉到对其领会的不够深入,一种能用其术,不知其道的感觉.在很多教材或者回答中,经常看多将动态规划放在递归这一部分中.当 ...

  7. 【BZOJ1042】硬币购物(动态规划,容斥原理)

    [BZOJ1042]硬币购物(动态规划,容斥原理) 题面 BZOJ Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬 ...

  8. c++矩阵连乘的动态规划算法并输出_算法面试必修课,动态规划基础题型归纳(三)

    动态规划(Dynamic Programming,简称DP),是大家都觉得比较难以掌握的算法.为了应付面试,我们经常会背诵一下DP问题的源码,其实,只要理解了思想,掌握基本的模型,然后再来点写代码的套 ...

  9. 【Java -- 算法】分治算法、动态规划、回溯法、贪心算法

    前言 一句话理解四种算法思想 分治:分而治之,先解决子问题,再将子问题的解合并求出原问题. 贪心:一条路走到黑,选择当下局部最优的路线,没有后悔药. 回溯:一条路走到黑,手握后悔药,可以无数次重来.( ...

  10. 动态规划经典题目-找零钱的最少硬币数

    文章目录 一.题目描述 二.解题思路(朴素版本) 1. 定义状态 2. 定义状态转移方程 3. 初始化 三.代码实现 四.优化 五.执行结果 一.题目描述 ​ 美国的硬币按照面值1, 5, 10, 2 ...

最新文章

  1. 顺序表-顺序表表示集合-交集( for + whlie ,不断遍历)
  2. Quartz 框架快速入门(二)
  3. C# 3.0 New Language Features (Part 1)
  4. EhCache复制:RMI与JGroups
  5. 中国人民大学教授杜小勇:One Size Does not Fit All?
  6. Linux内核安装-5.9.1为例
  7. c语言汉诺塔递归算法_Python进阶之递归函数的用法及其示例
  8. 20200113每日一句
  9. c 语言中的this指针,C++ this指针详解
  10. Linux日文教程,Ubuntu日语、法语输入法的设置
  11. 恢复服务器误删文件,云服务器误删文件恢复
  12. (13.1.3.9)PMBOK之三:十大知识领域之采购管理
  13. 2个方式快速解决:Word背景图片怎么设置
  14. c语言去除字符串中字母,C语言经典例题100例——C语言练习实例32解答(在字符串中删除指定字母或字符串)...
  15. S曲线C语言实现,利用robomodule+STM32F429+直流伺服电机进行简单验证
  16. 基于java的银行信用卡业务系统
  17. java39阶台阶_第四届蓝桥杯javaC组_第39级台阶
  18. 显著性假设(基础篇)
  19. 利用word2vec、textCNN、jieba对事故文本多分类及致因修复(三维向量)
  20. 从感知觉现象引发的对人工智能的一些思考

热门文章

  1. 磨刀不误砍柴工,掌握DEVC++的一些实用技巧
  2. Unity导入Goolgle.Protobuf.dll报错
  3. 【idea】两台电脑协同办公
  4. 【小月电子】XILINX FPGA开发板(XLOGIC_V1)系统学习教程-LESSON9简易测试系统
  5. 抓取lol全英雄图(不含皮肤)
  6. Pygame实战:这款“欢乐打地鼠”小游戏让几亿人“上瘾“?不玩绝对是你的损失。
  7. JS重点整理之JS原型链彻底搞清楚
  8. 2007五一[西北行] - 第二天:延安(窑洞,杨家岭,宝塔山...)
  9. 路由技术 -- 路由策略(Routing Policy)与策略路由(PBR,Policy-based Routing)技术
  10. 阅读笔记:利用Python进行数据分析第2版——第10章 数据聚合与分组运算