算法——贪心算法

本文介绍了贪心算法的基本思想,解题步骤,并通过圣诞老人分糖果和电影节选电影两个例题展示了贪心策略的应用。文章指出贪心算法在某些问题上能获得最优解,但并非所有情况都适用。


前言

贪心算法是我个人比较喜欢的算法,简单有效,思路往往很容易想到,但是要证明其正确性比较麻烦。


一、思想

贪心的意思在于在作出选择时,每次都要选择对自身最为有利的结果,保证自身利益的最大化。贪心算法就是利用这种贪心思想而得出一种算法。对于一个较大的问题,通过一种贪心策略,把复杂的问题划分为多个小问题,并且找到每个子问题的最优解,以此来获得整个问题的最优解。也就是说贪心算法是一种在每一步选择中都采取在当前状态下最好的选择,从而希望得到结果也是是最好的算法。但是贪心算法并不是在所有问题上都能得到整体最优解,只是可以在相当广泛的问题上得到整体最优解或者整体最优解的近似。

二、解题步骤

  1. 制定一个贪心策略,想好如何划分子问题以及如何求解子问题(不同的贪心策略往往可以得到不同的答案,但通常只有一个策略对应着正确的答案)
  2. 划分子问题
  3. 求解子问题的最优解
  4. 将所有子问题的解合并成整体的解

三、例题

1.圣诞老人的礼物

描述
圣诞节来临了,在城市A中圣诞老人准备分发糖果,现在有多箱不同的糖果,每箱糖果有自己的价值和重量,每箱糖果都可以拆分成任意散装组合带走。圣诞老人的驯鹿最多只能承受一定重量的糖果,请问圣诞老人最多能带走多大价值的糖果。

输入
第一行由两个部分组成,分别为糖果箱数正整数n(1 <= n <= 100),驯鹿能承受的最大重量正整数w(0 < w < 10000),两个数用空格隔开。其余n行每行对应一箱糖果,由两部分组成,分别为一箱糖果的价值正整数v和重量正整数w,中间用空格隔开。

输出
输出圣诞老人能带走的糖果的最大总价值,保留1位小数。输出为一行,以换行符结束。

样例输入
4 15
100 4
412 8
266 7
591 2

样例输出
1193.0

解题思路
计算每箱糖果的价值/重量比,并且每次都先选最大的(贪心策略),对价值重量比大的糖果尽可能多装,装完了再退而求其次装第二大的,以此类推。

示例代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const double eps = 1e-6;		//足够小,可以看作是0
struct Candy
{
   
   
	int v;			//价值
	int w;		//重量
	bool operator < (const Candy& c) const
	{
   
   //运算符重载,将用于下面的sort函数中
		return double
### 贪心算法中当前字段和的概念与实现 贪心算法的核心在于通过局部最优解逐步构造全局最优解。在最大字段和问题中,当前字段和(Current Sum)是指从数组的某个起始位置开始,到当前位置为止的所有元素之和[^1]。如果当前字段和为负数,则会拉低后续元素的总和,因此选择从下一个元素重新开始计算字段和,这是贪心策略的关键所在。 #### 当前字段和的原理 在最大子段和问题中,贪心算法通过以下方式实现局部最优解: - 如果当前字段和为负数,则放弃当前字段和,从下一个元素重新开始计算。 - 记录所有可能的字段和中的最大值,作为最终结果。 这种策略确保了每次决策都基于当前的最佳选择,从而避免了不必要的计算。例如,在数组 `nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]` 中,当遍历到第 1 个元素 `-2` 时,由于当前字段和为负数,选择从第 2 个元素 `1` 开始重新计算字段和[^2]。 #### 实现代码 以下是使用贪心算法求解最大字段和问题的 C++ 实现: ```cpp #include <iostream> using namespace std; int main() { int n; cin >> n; int a[n]; for (int i = 0; i < n; ++i) { cin >> a[i]; } int maxSum = a[0]; // 初始化最大字段和 int currentSum = a[0]; // 初始化当前字段和 for (int i = 1; i < n; ++i) { if (currentSum < 0) { currentSum = a[i]; // 如果当前字段和为负数,则重置为当前元素 } else { currentSum += a[i]; // 否则累加当前元素 } if (currentSum > maxSum) { maxSum = currentSum; // 更新最大字段和 } } cout << maxSum << endl; } ``` 在上述代码中,`currentSum` 表示当前字段和,`maxSum` 表示全局最大字段和。当 `currentSum` 为负数时,选择从当前元素重新开始计算字段和,从而保证了局部最优解的选取[^4]。 #### 时间复杂度分析 该算法的时间复杂度为 O(n),其中 n 是数组的长度。由于只需要一次遍历即可完成计算,因此效率较高。此外,空间复杂度为 O(1),因为只使用了常量级别的额外空间[^2]。 #### 总结 贪心算法通过局部最优解逐步构建全局最优解。在最大字段和问题中,当前字段和的概念用于判断是否需要重新开始计算字段和,从而实现高效的求解过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值