您的位置:首页 > 其它

动态规划之硬币表示问题

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]]。

代码实现

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
);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: