原文:http://www.cnblogs.com/python27/archive/2013/09/05/3303721.html

问题描述

  假设我们有8种不同面值的硬币{1,2,5,10,20,50,100,200},用这些硬币组合够成一个给定的数值n。例如n=200,那么一种可能的组合方式为 200 = 3 * 1 + 1*2 + 1*5 + 2*20 + 1 * 50 + 1 * 100. 问总过有多少种可能的组合方式? (这道题目来自著名编程网站ProjectEuler, 点击这里查看原题目) 类似的题目还有:

  [华为面试题] 1分2分5分的硬币三种,组合成1角,共有多少种组合

  [创新工厂笔试题] 有1分,2分,5分,10分四种硬币,每种硬币数量无限,给定n分钱,有多少中组合可以组成n分钱。

这个问题在链家的一次线下笔试碰到过。当时题目是1,2,5角硬币拼凑成sum的组合数。

当时的做法是sum/5=i,(sum-5*i)/2=j,写了几个for循环,效率较低。(面值越多复杂度越高)

后来发现这个题用动态规划很好做。

问题分析

  给定一个数值sum,假设我们有m种不同类型的硬币{V1, V2, ..., Vm},如果要组合成sum,那么我们有

sum = x1 * V1 + x2 * V2 + ... + xm * Vm

求所有可能的组合数,就是求满足前面等值的系数{x1, x2, ..., xm}的所有可能个数。

定义:dp[i][sum] = 用前i种硬币构成sum 的所有组合数。

那么题目的问题实际上就是求dp[m][sum],即用前m种硬币(所有硬币)构成sum的所有组合数

dp[i][sum] = dp[i-1][sum - 0*Vm] + dp[i-1][sum - 1*Vm]

+ dp[i-1][sum - 2*Vm] + ... + dp[i-1][sum - K*Vm]; 其中K = sum / Vm

  换一种更抽象的数学描述就是:

通过此公式,我们可以看到问题被一步步缩小,那么初始情况是什么呢?如果sum=0,那么无论有前多少种来组合0,只有一种可能,就是各个系数都等于0;

dp[i][0] = 1   // i = 0, 1, 2, ... , m

  如果我们用二位数组表示dp[i][sum], 我们发现第i行的值全部依赖与i-1行的值,所以我们可以逐行求解该数组。

理解:也就是将用前i种面值组合的情况转化为前i-1的情况,

即用前i-1种面值拼凑成sum-k*Vm的情况加起来就是前i种的组合数。

二维数组解法:

public static int count(int[] coins,int n){int[][] dp = new int[coins.length+1][n+1];for(int i=0;i<coins.length+1;i++)dp[i][0] = 1;   //初始化,用前i种面值组合成0的方案为1for(int i=1;i<=coins.length;i++)for(int j=1;j<=n;j++)for(int k=0;k<=j/coins[i-1];k++)dp[i][j] += dp[i-1][j-k*coins[i-1]];return dp[coins.length][n];}

一维数组解法:

public static int countWays(int[] coins,int n) {   int[] dp = new int[n+1];         dp[0] = 1;  for(int i = 0;i < coins.length;++i){  for(int j = coins[i];j <= n;++j){ dp[j] += dp[j-coins[i]];   }  }  return dp[n];  }

解法只能输出组合数,不能输出组合情况,待解决。

算法题 硬币组合问题相关推荐

  1. 动态规划算法计算硬币组合

    你有三种硬币,分别面值2元,5元和7元,每种硬币都有足够多.买一本书需要27元.如何用最少的硬币组合正好付清,不需要对方找钱? 这道题是lintcode编号669的Coin Change问题. 实现方 ...

  2. 算法题-排列组合问题

    27.Algorithm Gossip: 排列组合 说明 将一组数字.字母或符号进行排列,以得到不同的组合顺序,例如1 2 3这三个数的排列组合有:1 2 3.1 3 2.2 1 3.2 3 1.3 ...

  3. C++经典算法题-排列组合

    27.Algorithm Gossip: 排列组合 说明 将一组数字.字母或符号进行排列,以得到不同的组合顺序,例如1 2 3这三个数的排列组合有: 1 2 3.1 3 2.2 1 3.2 3 1.3 ...

  4. 90 个名企笔试题和算法题

    名企笔试 名企笔试:美团2016招聘笔试(股票交易日) 名企笔试:搜狐2016招聘笔试题(扎金花) 名企笔试:凤凰网2015招聘(二分查找) 名企笔试:4399游戏校招笔试题(快速排序) 名企笔试:蘑 ...

  5. 目录:名企笔试 + 算法题

    名企笔试:美团2016招聘笔试(股票交易日) 名企笔试:搜狐2016招聘笔试题(扎金花) 名企笔试:凤凰网2015招聘(二分查找) 名企笔试:4399游戏校招笔试题(快速排序) 名企笔试:蘑菇街201 ...

  6. 搬:90 个名企笔试题和算法题

    名企笔试 名企笔试:美团2016招聘笔试(股票交易日) 名企笔试:搜狐2016招聘笔试题(扎金花) 名企笔试:凤凰网2015招聘(二分查找) 名企笔试:4399游戏校招笔试题(快速排序) 名企笔试:蘑 ...

  7. 【美团点评2020校招测试方向笔试题】算法题部分1.删除字符 2.队列组合排序 3.寻找最小子字符串 4.最大矩形 5.最短送餐路程计算

    做题网址:点击进入 1.[编程题]删除字符 将给定的字符串,按照规则删除字符,输出删除后的字符串.删除规则为:相同字符连续,则删除,如"aaaab"删除后的字符串为"b& ...

  8. java数组排列组合_java算法题--递归求数组中数字排列组合问题

    java算法题–递归求数组中数字排列组合问题 题目:有一个数组{1,2,3},输出数组中数字的所有可能组合: 比如:123.132.213- 解题思路 通过递归不停的交换数组中的两个数(当然,肯定是有 ...

  9. 4.2.3 编程题《将一笔钱换算成1分、2分和5分的硬币组合》

    将一笔钱(大于8分,小于1元,精确到分)换算成1分.2分和5分的硬币组合。输入金额,问有几种换算方法?要求每种硬币至少有一枚。 [输入形式] 从键盘输入一个正整数n. [输入输出样例1](下划线部分表 ...

最新文章

  1. c# 实现二进制文件读写、ini文件读写以及一些文件和目录的常用操作,在某些特定情况下会用到,如录波文件要保存.dat
  2. jsp的session介绍 (转)
  3. 台湾国立大学郭彦甫Matlab教程笔记(21)linear equations(高斯消去法和追赶法)
  4. java调接口传值_关于调用第三方接口时传递参数是File类型的解决方式
  5. Linux+写数据异常断电,同事处理异常断电数据库状态变为SUSPECT过程
  6. 2020哔哩哔哩流量生态白皮书:流量趋势与up主生存状况调研
  7. spring Mvc 执行原理 及 xml注解配置说明 (六)
  8. Dgraph安装以及使用1
  9. 同余方程-NOIP2012TGD2T1
  10. 什么是 GPL GNU,自由软件
  11. 三洋p6系列伺服电机说明书_松下A6系列驱动器电路板坏了维修_常州凌科自动化科技有限公司...
  12. html页面实现英中语言选择,js代码实现网站中英文相互翻译
  13. 机器学习十大算法案例
  14. 专访阿里巴巴研究员赵海平:从Facebook到阿里巴巴
  15. weex_iOS集成
  16. sphinxapi.php 详解,【转】Sphinx PHP api全文检索的例子
  17. 微信小程序 - 获取汉字拼音首字母(汉字英文首字母)
  18. 计算机检索自考,计算机信息检索02139自考资料(25页)-原创力文档
  19. JAVA运行内存的设置
  20. 【DB笔试面试608】在Oracle中,如何使用STA来生成SQL Profile?

热门文章

  1. 如何将npm升级到最新版本
  2. STM32—sg90编程
  3. xgboost.fit函数
  4. instruction-tuning
  5. 服务器拒绝了您发送离线文件的请求,处理qq发送离线文件被提示“服务器拒绝了您发送离线文件”的方法...
  6. 使用Java对HBase进行操作(三)
  7. PHp网站建设,期末大作业-海贼王主题【包含前后台】
  8. Backlight 背光
  9. UNIX环境编程学习笔记(1):——出错处理errno
  10. (六)Flutter 基础部件 TextView 和TextStyle Flutter 容器 装饰盒子 边框 圆角 阴影 形状 渐变 背景图像