题目:硬币很多种,价值各不同。拼成一个数。最少用几个?
输入:coins = {1, 2, 3, 4} target = 10
输出:3
解释:最少使用的硬币数是3:包含两个4和一个2
思路分析:
1.贪心法:从最大硬币值开始,逐步往低试。
反例:coins = {1,5,11} target = 20; 应输出:4(4*5);贪心法输出:6(11+5+4*1)。贪心法pass。
2.动态规划:
解空间树:
![](https://i-blog.csdnimg.cn/blog_migrate/7d669e77d8a909d09f4076965234017b.png)
代码实现:
#include<iostream>
#include<vector>
using namespace std;
//备忘模型
int GetMemo(vector<int>& coins,vector<int>& memo, int target)
{
if (memo[target] == -2) {
int result = -1;
for (int coin : coins) {
if (coin <= target) {
int temp = GetMemo(coins, memo, target - coin);
if (temp != -1 && (result == -1 || temp + 1 < result))
result = temp + 1;
}
}
memo[target] = result;
}
return memo[target];
}
int GetCoins(vector<int>& coins,int target)
{
vector<int> memo(target + 1, -2); //-2表示未计算,-1表示无解
memo[0] = 0;
return GetMemo(coins,memo, target);
}
//演绎模型
int GetCoins1(vector<int>& coins, int target)
{
vector<int> memo(target + 1);
memo[0] = 0;
for (int i = 1; i < memo.size(); ++i) {
int result = -1;
for (int coin : coins) {
if (coin <= i) {
int temp = memo[i - coin];
if (temp != -1 && (result == -1 || result > temp + 1))
result = temp + 1;
}
}
memo[i] = result;
}
return memo[target];
}
int main()
{
vector<int> coins({ 1,2,3,4 });
vector<int> coins1({ 1,5,11 });
cout << GetCoins(coins1, 20) << endl;
cout << GetCoins1(coins1, 20) << endl;
return 0;
}
箴言录:
君子欲讷于言而敏于行。