归纳于http://www.cnblogs.com/grandyang/p/7669088.html
原题https://leetcode.com/problems/coin-change-2/description/
518. Coin Change 2(Medium)
You are given coins of different denominations and a total amount of money. Write a function to compute the number of
combinations that make up that amount. You may assume that you have infinite number of each kind of coin.
Note: You can assume that
0 <= amount <= 5000
1 <= coin <= 5000
the number of coins is less than 500
the answer is guaranteed to fit into signed 32-bit integer
Example 1:
Input: amount = 5, coins = [1, 2, 5]
Output: 4
Explanation: there are four ways to make up the amount:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
Example 2:
Input: amount = 3, coins = [2]
Output: 0
Explanation: the amount of 3 cannot be made up just with coins of 2.
Example 3:
Input: amount = 10, coins = [10]
Output: 1
问题描述
给一个总钱数amount,给一个硬币种类数组,每种硬币的数量你可以想象成足够大,问:允许使用同种硬币,一个有多少种硬币组合方式刚好能凑成总钱数amount?
分析
比如我们有两个硬币[1,2],钱数为5,那么钱数的5的组成方法是可以看作两部分组成,一种是由硬币1单独组成,那么仅有一种情况(1+1+1+1+1);另一种是由1和2共同组成,说明我们的组成方法中至少需要由一个2,所以此时我们先取出一个硬币2,那么我们只要拼出钱数为3即可,这个3还是可以用硬币1和2来拼,所以就相当于求由硬币[1,2]组成的钱数为3的总组合方法数。
动态规划:dp[i][j]表示用前i个硬币组成钱数为j的不同组合方法
递归式:dp[i][j] = dp[i - 1][j] + (j >= coins[i - 1] ? dp[i][j - coins[i - 1]] : 0);
代码
class Solution { public: int change(int amount, vector<int>& coins) { if(amount==0) return 1; if(coins.empty()) return 0; vector<vector<int>> dp(coins.size()+1,vector<int>(amount+1,0)); dp[0][0]=1; //dp[0][j!=0]已被初始化为0了 for(int i=1;i<=coins.size();++i) { dp[i][0]=1; for(int j=1;j<=amount;++j) { if(j>=coins[i-1]) dp[i][j]=dp[i-1][j]+dp[i][j-coins[i-1]]; else dp[i][j]=dp[i-1][j]; /*调试用 printf("dp[%d][%d] = dp[%d-1][%d] + (%d >= coins[%d-1] ? dp[%d][%d - coins[%d-1]] : 0)", i, j, i, j, j, i, i, j, i); printf("= dp[%d][%d] + (%d >= %d ? dp[%d][%d - %d] : 0)", i-1, j,j,coins[i-1],i,j, coins[i - 1]); dp[i][j] = dp[i - 1][j] + (j >= coins[i - 1] ? dp[i][j - coins[i - 1]] : 0); printf("= %d\n\n", dp[i][j]); */ } } return dp[coins.size()][amount]; } };
原文地址:https://www.cnblogs.com/Joezzz/p/9744370.html