题目:
有数组penny,penny中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。
给定数组penny及它的大小(小于等于50),同时给定一个整数aim,请返回有多少种方法可以凑成aim。
测试样例:
[1,2,4],3,3
返回:2
penny的长度为n,那么生成行数为n,列数为aim+1的数组dp[i][j],表示使用penny[0,....i]货币的情况下,组成钱数j的方法数。
初始值第一列为1(组成钱数为0的方法只有1种,就是取0张),第一行的值是penny[0]的倍数为1,否则为0.
dp[i][j]=dp[i-1][j](0张penny[i])+dp[i-1][j-1*penny[i]](1张penny[i])+dp[i-1][j-2*penny[i]](2张penny[i])+..............+dp[i-1][j-m*penny[i]](m张penny[i],j-m*penny[i]>0则继续,否则停止)
化简后dp[i][j]=dp[i][j-penny[i]]+dp[i-1][j]
Java代码:
import java.util.*;
public class Exchange {
public int countWays(int[] penny, int n, int aim) {
/*
如果penny的长度为n,那么生成行数为n,列数为aim+1的矩阵dp,dp[i][j]的含义是在使用penny[0,....,i]货币的情况下,
组成钱数j的方法数
计算时先从左往右再从上往下计算,初始值第一列为1,第一行只有是penny[0]的倍数时才为1。
dp[i][j]=完全不用penny[i]货币时dp[i-1][j]+1张penny[i]时dp[i-1][j-1*penny[i]]+....+m张penny时dp[i-1][j-m*
penny[i](j-m*penny[i]<0时停止)
化简之后dp[i][j]=dp[i][j-arr[i]]+dp[i-1][j]
*/
/*int[][] dp=new int[n][aim+1];
if(penny==null||penny.length==0||aim<0)
return 0;
//第一列为1
for(int i=0;i<n;i++)
{
dp[i][0]=1;
}
//第一行是penny[0]倍数为1,否则为0
for(int i=1;i<=aim;i++)
{
if(i%penny[0]==0)
{
dp[0][i]=1;
}
else
dp[0][i]=0;
}
for(int i=1;i<n;i++)
for(int j=1;j<aim+1;j++)
{
if(j>=penny[i])
dp[i][j]=dp[i][j-penny[i]]+dp[i-1][j];
else
dp[i][j]=dp[i-1][j];//当钱数比penny[i]还小时,要考虑到
}
return dp[n-1][aim];*/
/*
化简后
*/
int []dp=new int[aim+1];
dp[0]=1;
for(int i=0;i<n;i++)
for(int j=penny[i];j<=aim;j++)
{
dp[j]+=dp[j-penny[i]];
}
return dp[aim];
}
}