題目:
有數組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];
}
}