换零钱:动态规划

换零钱:动态规划

换零钱有两类问题,分别对应着一维动态规划和二维动态规划

求最少硬币数

它的思路是一维动态规划:dp[i]=1+min(dp[i-k])

dp[i]=1+min(dp[i-k])的1表示选择当前种类的一个硬币,min(dp[i-k])表示要凑齐剩余金额的最少硬币数。通过Min操作,我们找到了使得dp[i-k]最小的k

求换硬币策略数

题目描述

有一个数组changes,changes中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,对于一个给定值x,请设计一个高效算法,计算组成这个值的方案数。

给定一个int数组changes,代表所有零钱,同时给定它的大小n,另外给定一个正整数x,请返回组成x的方案数,保证n小于等于100且x小于等于10000。

测试样例:

[5,10,25,1],4,15
返回:6

测试样例:

[5,10,25,1],4,0
返回:1

链接:https://www.nowcoder.com/questionTerminal/185dc37412de446bbfff6bd21e4356ec?f=discussion
来源:牛客网

import java.util.*;
 
public class Exchange {
    public int countWays(int[] changes, int n, int x) {
        // write code here
        //dp[i][j]表示使用changes[0~i]的钱币组成金额j的方法数
        int[][] dp=new int[n][x+1];
        //第一列全为1,因为组成0元就只有一种方法
        for(int i=0;i<n;i++)
            dp[i][0]=1;
        //第一行只有changes[0]的整数倍的金额才能有1种方法
        for(int j=0;j*changes[0]<=x;j++){
            dp[0][j*changes[0]]=1;
        }
        //从位置(1,1)开始遍历
        for(int i=1;i<n;i++){
            for(int j=1;j<=x;j++){
                //关键:使用0~i的钱币组成j-changes[i]金额的方法数+使用0~i-1钱币组成j的方法数
                dp[i][j]=dp[i-1][j]+(j-changes[i]>=0?dp[i][j-changes[i]]:0);
            }
        }
         
        return dp[n-1][x];
    }
}

思路是,用0-i的钱币组成j的策略数=用0-(i-1)的钱币组成j的策略数(也就是不使用第i种钱币的意思)+用0-i的钱币组成j-i的策略数(也就是使用第i个种钱币)

初始化是对第一行和第一列的初始化

posted @ 2020-03-22 21:24  别再闹了  阅读(241)  评论(0)    收藏  举报