高頻算法面試題學習總結----動態規劃3:換硬幣

題目:硬幣很多種,價值各不同。拼成一個數。最少用幾個?
輸入: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.動態規劃:

解空間樹:

圖1

代碼實現:

#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;
}

 

箴言錄:

君子欲訥於言而敏於行。 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章