硬币组合问题
来源:互联网 发布:java 动态网页开发 编辑:程序博客网 时间:2024/05/18 10:53
题目
假设我们有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. 问总过有多少种可能的组合方式?原题 转载
分析
这道题目是非常经典的动态规划算法题。给定一个数值sum,假设我们有m种不同类型的硬币
求所有可能的组合数,就是求满足前面等值的系数
思路1:
用暴力枚举,各个系数可能的取值无非是
,这对于硬币种类数较小还可以应付。
思路2:
从上面的分析中我们也可以这么考虑,我们希望用m种硬币构成sum,根据最后一个硬币
…
其中
定义dp[i][sum] = 用前i种硬币构成sum 的所有组合数。
那么题目的问题实际上就是求dp[m][sum],即用前m种硬币(所有硬币)构成sum的所有组合数。
在上面的联合等式中,当
其中
初始情况:如果sum=0,那么无论有前多少种来组合0,只有一种可能,就是各个系数都等于0,
如果我们用二位数组表示dp[i][sum], 我们发现第i行的值全部依赖与i-1行的值,所以我们可以逐行求解该数组。如果前0种硬币要组成sum,我们规定为dp[0][sum] = 0。
思路3:硬币组合问题,本质上就是组合数的问题,解决组合问题,非常经典的算法是回溯算法,它在无限的解空间中深度优先搜索。
第一种动态规划算法实现如下:
import java.util.Scanner;/** * 有几种纸币面值1, 5, 10, 20, 50, 100元,假设每种面值的纸币无限,用它们组合成N元。找出所有的组合数。 * @author ShaoCheng * @version 1.0 2015-9-19 */public class Solution { /** * @param N 输入的总和N * @return 所有的组合数 */ public long getNumberOfCombinations(int N) { int coinKinds = coins.length; int[][] dp = new int[coinKinds+1][N+1]; for(int i = 0; i <= coinKinds; i++){ //初始化 for(int j = 0; j <= N; ++j){ dp[i][j] = 0; } } for(int i = 0; i <= coinKinds; i++){ dp[i][0] = 1;//前i种纸币组合成0,只有一种情况就是个数均为0 } for(int i = 1; i <= coinKinds; i++){ for(int j = 1; j <= N; j++){ dp[i][j] = 0; for(int k = 0; k <= j / coins[i-1]; k++){ dp[i][j] += dp[i-1][j - k*coins[i-1]]; } } } return dp[coinKinds][N]; } public static void main(String[] args){ Solution sl = new Solution(); Scanner scanner = new Scanner(System.in); int N = scanner.nextInt(); long res = sl.getNumberOfCombinations(N); System.out.println(res); scanner.close(); } public Solution() { // TODO Auto-generated constructor stub coins = new int[]{1, 5, 10, 20, 50, 100}; } private int[] coins;}
回溯算法实现如下:
import java.util.Arrays;import java.util.Scanner;/** * 有几种纸币面值1, 5, 10, 20, 50, 100元,假设每种面值的纸币无限,用它们组合成N元。找出所有的组合数。 * @author ShaoCheng * @version 1.1 2015-9-20 */public class Solution { /** * @param N 输入的总和N * @return 所有的组合数 */ public long getNumberOfCombinations(int N) { long sum = 0; return getNumberOfCombinations(N, sum, 0); } public long getNumberOfCombinations(int N, long sum, int start){ long count = 0; for(int i = start; i < coins.length; i++){ sum += coins[i]; if(sum == N){ count++; break; } if(sum < N){ count += getNumberOfCombinations(N, sum, i); sum -= coins[i]; } else break; } return count; } public static void main(String[] args){ Solution sl = new Solution(); Scanner scanner = new Scanner(System.in); int N = scanner.nextInt(); long res = sl.getNumberOfCombinations(N); System.out.println(res); scanner.close(); } public Solution() { // TODO Auto-generated constructor stub coins = new int[]{1, 5, 10, 20, 100, 50}; //如果乱序,应先排序 Arrays.sort(coins); } private int[] coins;}
- 硬币组合问题
- 硬币组合问题
- 硬币面值组合问题
- 硬币组合问题
- 硬币组合问题
- 硬币组合问题
- 硬币组合问题之最少硬币个数
- CI8.7--硬币组合问题
- Recursion 硬币组合问题 @CareerCup
- 硬币组合问题-动态规划
- 动态规划应用—硬币组合问题
- 动态规划之硬币组合问题
- 【编程之法】硬币面值组合问题
- 动态规划之硬币面值组合问题
- 动态规划-最少硬币组合问题
- 硬币组合
- 硬币组合
- 回溯法解组合问题——硬币问题
- USACO 1.3 Ski Course Design
- LintCode --find-the-missing-number(寻找缺失的数)
- C++ Primer Plus(第六版)--学习杂记(第六章)
- 怎样网站加速
- 从H264/H265码流中获取宽、高及帧率
- 硬币组合问题
- POJ 2488 A Knight's Journey
- swift 静态方法
- java.lang.IllegalArgumentException: Mapped Statements collection does not....
- 学习方法
- Struts2:配置Action——包和命名空间
- ucos在M3中的中断嵌套机制
- 分享一种线程池实现方法
- 输入url到返回页面的过程