题目:假设银行里一共有n种硬币,第一种硬币的价值为V1。假设想把k元兑换成零钱,一共有多少种兑换方案。
例如,一共有1,2,5三种硬币,k = 5,则有以下兑换方案:11111,1112,122,5。共有4中兑换方案。
动态规划问题最重要的是要找到状态转移方程!!!
用dp[i][sum]表示使用前i种硬币来组合sum这些钱有多少种兑换方案。那么
dp[i][sum] = dp[i-1][sum - 0*Vi] + dp[i-1][sum-1*Vi]+...+dp[i-1][sum-k*Vi]
其中k = sum / Vi
理解:拿sum=6,i=3来解释一下。其中V1=1,V2=2,V3=5,也就是Vi=5。而dp[3][6]就等于在不使用5这个硬币的时候有多少种组合方式加上使用一个5硬币有多少种组合方式。因为sum=6,最多只能有一个5硬币,所以k=1。
代码如下
int coinCombinations(int coins[], int coinKinds, int sum)
{
vector<vector<int> > dp(coinKinds + 1, vector<int>(sum + 1, 0));
for (int i = 0; i <= coinKinds; ++i) //递推初始条件
{
dp[i][0] = 1;
}
for (int i = 1; i <= coinKinds; ++i)
{
for (int j = 1; j <= sum; ++j)
{
//j / coins[i-1]表示能取的该硬币的最大数量。
//j / coins[i-1]是理解这道题的关键所在
for (int k = 0; k <= j / coins[i - 1]; ++k) //i-1是因为coins是从0开始算起的。
{
dp[i][j] += dp[i - 1][j - k * coins[i - 1]];
}
}
}
return dp[coinKinds][sum];
}