算法设计与分析之贪心算法

1. 贪心算法简介

贪心算法(Greedy Algorithm)是一种基于贪心思想的算法策略。它通过每一步选择当前状态下最优的解决方案,从而逐步得到全局最优解。贪心算法通常在问题具有贪心选择性质最优子结构性质时被应用。

贪心算法的基本思想是,每一步选择当前情况下看起来最好的解决方案,而不考虑之后可能发生的情况。它不进行回溯,也不考虑全局最优解,而是根据局部最优选择来构建解决方案。

适合贪心算法具有的特征:

1、优化问题。

2、问题的求解可以划分为若干阶段。

3、能够制定出最优量度标准。

4、问题具有最优子结构性质。

贪心算法的步骤通常如下:

1、确定问题的最优子结构:问题的最优解可以通过子问题的最优解来构建。

2、定义贪心选择策略:确定每一步的最优选择。

3、构建解决方案:根据贪心选择策略,逐步构建问题的解决方案。

4、验证解决方案:检查贪心算法得到的解决方案是否满足问题的要求。

2. 找零钱问题

关于贪心算法的一个经典例子是找零钱问题(Coin Change Problem)。问题描述如下:给定一些不同面额的硬币和一个需要找零的金额,找出最少的硬币数量来凑出该金额。利用贪心算法解决该问题的思路如下:

(1)输入找零的金额和每种硬币的面额;

(2)从币值从高到低进行贪心策略;

(3)选择所要表示的币值;

(4)记录所选择的币值所要的数目,现金值实时更改;

(5)输出结果。

算法实现

#include <iostream>
#include <vector>
#include <algorithm>
	
std::vector<int> greedyCoinChange(std::vector<int>& coins, int amount) {
	std::vector<int> result;
	
	// 按面额从大到小排序硬币
	// std::sort(coins.begin(), coins.end(), std::greater<int>());	// 与下一行功能相同
	std::sort(coins.rbegin(), coins.rend()); // c.rbegin() 返回一个逆序迭代器,它指向容器c的最后一个元素
	
	for (auto coin : coins) {
		while (amount >= coin) {
			result.push_back(coin);
			amount -= coin;
		}
	}
	
	if (amount != 0) {
		// 找不到合适的硬币组合
		result.clear();
	}
	
	return result;
}
	
int main() {
	std::vector<int> coins = { 1, 5, 10, 25 };
	int amount = 47;
	
	std::vector<int> result = greedyCoinChange(coins, amount);
	
	if (!result.empty()) {
		std::cout << "找零的硬币数量:" << result.size() << std::endl;
		std::cout << "找零的硬币面额:";
		for (auto coin : result) {
			std::cout << coin << " ";
		}
		std::cout << std::endl;
	} else {
		std::cout << "无法找零。" << std::endl;
	}
	
	return 0;
}

在上述示例中,我们定义了一个greedyCoinChange函数,它接收一个硬币面额的向量coins和需要找零的金额amount。首先,我们将硬币面额按从大到小排序,以便每次选择最大面额的硬币。然后,我们循环遍历每个硬币,直到无法再选择该硬币为止。最后,如果剩余的金额不为0,则表示无法找零,返回空的结果。在main函数中,我们定义了一组硬币面额和需要找零的金额,并调用greedyCoinChange函数来获取找零的结果。如果结果不为空,我们输出找零的硬币数量和面额;否则,输出无法找零的信息。

例如,对于硬币面额为{1, 5, 10, 25},需要找零47的情况下,输出将会是:

找零的硬币数量:5
找零的硬币面额:25 10 10 1 1

这表示我们可以用5个硬币凑出47的金额,其中包括1个25分硬币、2个10分硬币和2个1分硬币。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值