动态规划之硬币表示问题
2016-01-07 10:10
323 查看
问题描述:
有数量不限的硬币,币值为25分、10分、5分和1分,请编写代码计算n分有几种表示法。
求解思路:
这也是典型的动态规划问题,我们可以这样考虑:当只有1分的硬币时,n从1到n分别有多少种表示方法;当有1分和5分的硬币时,n从1到n分别有多少种表示方法,因此类推,直到我们将1分、5分、10分和25分的硬币全部使用完。思想类似于0-1背包问题,0-1背包问题的具体求解方法可以参考我的上一篇博客动态规划之0-1背包问题。我们用数组coins[i]={1,5,10,25}表示各种币值,此时可以维护一张二维表ways[i][j],其中横坐标表示前i种表示币值,j表示硬币的总值,则ways[i][j]表示能用前i种硬币来表示j分的方法数。
当增加一种新的硬币币值时,有两种情况:
(1)不加入此种币值:ways[i][j]=ways[i-1][j];
(2)加入此种币值:加入该枚硬币之前的方法数为ways[i][j-coins[i]],那么加入该枚硬币之后构成j分的方法数也为ways[i][j-coins[i]]。
因此当增加一种新的币值时,j分的表示方法数为ways[i][j]=ways[i-1][j]+ways[i][j-coins[i]]。
代码实现:
有数量不限的硬币,币值为25分、10分、5分和1分,请编写代码计算n分有几种表示法。
求解思路:
这也是典型的动态规划问题,我们可以这样考虑:当只有1分的硬币时,n从1到n分别有多少种表示方法;当有1分和5分的硬币时,n从1到n分别有多少种表示方法,因此类推,直到我们将1分、5分、10分和25分的硬币全部使用完。思想类似于0-1背包问题,0-1背包问题的具体求解方法可以参考我的上一篇博客动态规划之0-1背包问题。我们用数组coins[i]={1,5,10,25}表示各种币值,此时可以维护一张二维表ways[i][j],其中横坐标表示前i种表示币值,j表示硬币的总值,则ways[i][j]表示能用前i种硬币来表示j分的方法数。
当增加一种新的硬币币值时,有两种情况:
(1)不加入此种币值:ways[i][j]=ways[i-1][j];
(2)加入此种币值:加入该枚硬币之前的方法数为ways[i][j-coins[i]],那么加入该枚硬币之后构成j分的方法数也为ways[i][j-coins[i]]。
因此当增加一种新的币值时,j分的表示方法数为ways[i][j]=ways[i-1][j]+ways[i][j-coins[i]]。
代码实现:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] coins = {1, 5, 10, 25}; int[][] ways = new int[4][n + 1]; for (int i = 0; i < 4; i++) ways[i][0] = 1; //第0行初始化为1 for (int j = 1; j <= n; j++) ways[0][j] = 1; //第0列初始化为1 for (int i = 1; i < 4; i++) { for (int j = 1; j <= n; j++) { if (j >= coins[i]) ways[i][j] = ways[i - 1][j] + ways[i][j - coins[i]]; else ways[i][j] = ways[i - 1][j]; } } System.out.println(ways[3] ); } }当然,维护二维表未免过于复杂,我们可以维护一张一维表,即用一维数组ways[j]来记录j分的表示方法数。改进的代码实现如下:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int []coins={1,5,10,25}; int []ways=new int[n+1]; ways[0]=1; for(int i=0;i<4;i++){ for(int j=coins[i];j<=n;j++){ ways[j]=ways[j]+ways[j-coins[i]]; } } System.out.println(ways ); } }
相关文章推荐
- Android——窗口层控制WindowManager.LayoutParams.type
- 【LinkIt One】驱动无法安装,提示“系统找不到指定的文件”
- Make a Neon Vector Shooter for iOS: The Warping Grid
- 随机概率算法
- Transductive Learning vs Inductive Learning
- Mac中常用的终端命令
- 构建一个倒排索引 A first take at building an inverted index
- UITableView中刷新单行cell与单个section段的方法
- QEMU模拟器/虚拟机简介
- 在selenium测试中使用XPATH功能函数starts-with、contains、descendant、ancestor、text()定位网页元素
- 领域驱动
- 奇葩json结构解析--key是数字的json处理
- 使用host模式搭建dockyard环境
- 如何更改tomcat7及以上版本内存设置
- How to Use a Shader to Dynamically Swap a Sprite's Colors
- tftp+dhcp+vsftp
- AndroidStudio里面怎么取消与SVN的关联
- LocalNotification本地通知
- android 9.png图片原理
- 小菜的性能日记 4 (合格的性能测试报告)