1. 兑换零钱II
先遍历物品,再遍历背包。递推公式:dp[j] += dp[j - coins[i]]
不能先遍历背包再遍历物品,如果物品在前,物品只遍历了一轮;而物品在后,物品会遍历多轮,出现重复组合的情况,如下表所示为先遍历背包再遍历物品的结果。
class Solution {
public:
int change(int amount, vector<int>& coins) {
int size = coins.size();
vector<int> dp(amount + 1, 0);
dp[0] = 1;
for(int i = 0; i < size; ++i){
for(int j = coins[i]; j <= amount; ++j){
dp[j] += dp[j - coins[i]];
}
}
return dp[amount];
}
};
2. 兑换零钱I
本题求钱币最小个数,那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数。所以外层for循环遍历物品,内层for遍历背包或者外层for遍历背包,内层for循环遍历物品都是可以的!
递推公式:dp[j] = min(dp[j], dp[j - arr[i]] + 1);
#include <climits>
class Solution {
public:
int minMoney(vector<int>& arr, int aim) {
// write code here
vector<int> dp(aim + 1, INT_MAX);
dp[0] = 0;
for(int i = 0; i < arr.size(); ++i){
for(int j = arr[i]; j <= aim; ++j){
if(dp[j - arr[i]] != INT_MAX){
dp[j] = min(dp[j], dp[j - arr[i]] + 1);
}
}
}
return dp[aim] == INT_MAX ? -1 : dp[aim];
}
};