动态规划之硬币表示问题

来源:互联网 发布:代理商域名转到阿里云 编辑:程序博客网 时间:2024/06/01 09:27

转载:http://m.blog.csdn.net/cy13299138237/article/details/50474271
问题描述:有数量不限的硬币,币值为25分、10分、5分和1分,请编写代码计算n分有几种表示法。

求解思路:这也是典型的动态规划问题,我们可以这样考虑:当只有1分的硬币时,n从1到n分别有多少种表示方法;当有1分和5分的硬币时,n从1到n分别有多少种表示方法,因此类推,直到我们将1分、5分、10分和25分的硬币全部使用完。。我们用数组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][n]);    }

当然,维护二维表未免过于复杂,我们可以维护一张一维表,即用一维数组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[n]);    }}
原创粉丝点击