題目:硬幣很多種,價值各不同。拼成一個數。最少用幾個?
輸入: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.動態規劃:
解空間樹:
代碼實現:
#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;
}
箴言錄:
君子欲訥於言而敏於行。