凑钱问题可以说是一类非常经典的算法了, 也就是给你一堆相应面额的钱币, 要求用最少的钱币数凑出一个数, 通常会用贪心和动态规划两种算法
用贪心算法的情况一般只有一种, 就是各个面额之间没有公因子的情况, 比如人民币, 就分为1, 5, 20, 50, 100; 这样的话每次就尽量取最大的就好了
可如果像这道题一样, 面额是随机输入的, 比方说我输入的是2, 3那么凑的话就不能按照贪心来凑了
就必须要用到动态规划, 其实这题本身就是一个动态规划中的完全背包问题 (即每一个硬币可以取无限次), 可以参考我写的完全背包题解: https://blog.csdn.net/a1097304791/article/details/83547276
是背包问题就要考虑到对容量的定义, 很显然只能是金额作为容量
注意由于是取最小的数, 所以除了dp[0]之外应该初始化为1<<30
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
if(amount < 0) return -1;
else if(amount == 0) return 0;
int dp[amount+5]; //凑成i元时的最少硬币数
dp[0] = 0;
for(int i = 1; i <= amount; i++)
dp[i] = 1<<30;
for(int j = 0; j < coins.size(); j++)
for(int i = 1; i <= amount; i++){
if(i >= coins[j])
dp[i] = min(dp[i], dp[i-coins[j]]+1);
}
if(dp[amount] > amount) return -1; //特殊条件
return dp[amount];
}
};