經典算法——貪婪算法

2024年2月6日 28点热度 0人点赞

貪婪算法教程

貪婪算法是一種在每一步選擇中都采取在當前狀態下最好或最優(即局部最優)的解決方案,從而期望導致結果是全局最優的一種策略。這種算法並不從整體上考慮所有可能的選擇,而是做出即時的決定,並且一旦做了決定就不再更改。

貪婪算法的基本步驟:

1. 定義問題的最優子結構:問題可以分解為多個相互獨立的子問題。

2. 選擇貪心策略:確定一個量度標準或規則來指導每一步決策,使得每次都能獲得局部最優解。

3. 遞歸地構造解決方案:按照貪心策略,每一步根據當前狀態作出最優決策,逐步構建最終解。

4. 證明算法正確性:通常需要證明對於該問題,采用貪心策略能得到全局最優解,或者至少是一個近似解。

C 示例:找零錢問題(硬幣找零)

假設你有一組面額各異的硬幣,要找給定金額的最少硬幣數量。貪心策略通常是先盡量用大面額的硬幣進行找零。

#include <iostream>
#include <vector>
#include <algorithm>
// 硬幣面額數組
std::vector<int> coin_values = { 1, 5, 10, 25 }; // 假設有1元、5元、10元和25元四種面額的硬幣
// 貪心算法實現找零
std::vector<int> greedyChange(int amount) {
	std::vector<int> result;
	while (amount > 0) {
		// 按照降序排列的硬幣面額尋找當前能使用的最大面額硬幣
		auto it = std::upper_bound(coin_values.begin(), coin_values.end(), amount);
		if (it == coin_values.begin()) {
			// 如果無法找到大於或等於剩餘金額的硬幣,則使用最小面額硬幣
			it--;
		}
		int coin_to_use = *it;
		// 計算當前面額硬幣的數量
		int count = amount / coin_to_use;
		for (int i = 0; i < count;   i) {
			result.push_back(coin_to_use);
		}
		// 更新剩餘待找零金額
		amount %= coin_to_use;
	}
	return result;
}
int main() {
	int target_amount = 36; // 需要找零的總金額
	std::vector<int> change_coins = greedyChange(target_amount);
	std::cout << "The minimum number of coins required to make change for " << target_amount << " is: ";
	std::cout << change_coins.size() << "\n";
	std::cout << "Coin distribution: ";
	for (int coin : change_coins) {
		std::cout << coin << " ";
	}
	std::cout << "\n";
	return 0;
}

在這個例子中,我們首先對硬幣面額按降序排序,然後每次都嘗試使用盡可能大的面額硬幣來減少剩餘找零金額。直到剩餘金額為0為止。註意,此示例假設硬幣面額適合貪心算法解決問題,即不存在硬幣面額組合無法通過貪心算法得到最少硬幣數目的情況。在某些特定硬幣面額情況下,貪心算法並不能確保得到全局最優解(如硬幣面額為{1, 3, 4}時找零7)。