算法学习:贪心算法

14天阅读挑战赛
*努力是为了不平庸~


系列文章目录

第一章 算法简介
第二章 贪心算法


2.1贪心算法

百度百科中,贪心算法(greedy algorithm ,又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。说人话就是只顾眼前利益,不从长远做打算。我们经常会听到这些话:“人要活在当下”“看清楚眼前”……贪心算法正是“活在当下,看清楚眼前”的办法,从问题的初始解开始,一步一步地做出当前最好的选择,逐步逼近问题的目标,尽可能地得到最优解,即使达不到最优解,也可以得到最优解的近似解

贪心算法在解决问题的策略上“目光短浅”,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。换言之,贪心算法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。贪心算法能得到许多问题的整体最优解或整体最优解的近似解。因此,贪心算法在实际中得到大量的应用。
在贪心算法中,我们需要注意以下几个问题。

  1. 没有后悔药。一旦做出选择,不可以反悔。we
  2. 有可能得到的不是最优解,而是最优解的近似解。
  3. 选择什么样的贪心策略,直接决定算法的好坏。

那么具体怎么去利用贪心算法呢?下面介绍基本流程:选择贪心策略,然后得到局部最优解,然后得到全局最优解。具体流程如下所示:

  1. 贪心策略:首先要确定贪心策略,选择当前看上去最好的一个方案。例如,挑选苹果,如果你认为个大的是最好的,那你每次都从苹果堆中拿一个最大的,作为局部最优解,贪心策略就是选择当前最大的苹果;如果你认为最红的苹果是最好的,那你每次都从苹果堆中拿一个最红的,贪心策略就是选择当前最红的苹果。因此根据求解目标不同,贪心策略也会不同。
  2. 局部最优解:根据贪心策略,一步一步地得到局部最优解。例如,第一次选一个最大的苹果放起来,记为 a 1 a_1 a1,第二次再从剩下的苹果堆中选择一个最大的苹果放起来,记为 a 2 a_2 a2,以此类推。
  3. 全局最优解:把所有的局部最优解合成为原来问题的一个最优解 ( a 1 , a 2 , … ) (a_1,a_2,…) a1a2)。熟知的冒泡算法就属于贪心算法

最优装载问题、背包问题、会议安排、最短路径、哈夫曼编码、最小生成树都利用了贪心算法的思想,下面进行逐个讲解。

2.2最优装载问题

首先叙述解决流程,形成完整的思考流程。
首先,分析问题并想出算法的设计思路(文字叙述)。
然后,给出图解思路。
之后,编写伪代码。
最后,给出完整代码。
还有一点,分析算法的复杂度,并思考改进思路。

2.2.1问题描述:

有一批集装箱要装上一艘载重量为 c c c的轮船。其中集装箱i的重量为 W i W_i Wi。最优装载问题要求确定在装载体积不受限制的情况下,将尽可能的集装箱装上轮船。(意思就是在不超过载重量的情况下最多能装多少)

2.2.2分析问题&设计思路:

最优装载问题可以利用贪心算法去求解,题目中要求的是装尽可能多的集装箱,船的载重量最大为 c c c且固定的,那么优先将重量小的物体放进去就可以装载尽可能多的集装箱。这里贪心策略选择的就是先装重量最轻者。就可以从局部最优解得到全局最优解。
设计思路:

  1. 当载重量为定值 c c c时, W i W_i Wi越小时,可装载的集装箱数量 n n n越大。只要依次选择最小重量集装箱,直到不能再装为止。
  2. n n n个集装箱的重量从小到大(非递减)排序,然后根据贪心策略尽可能多地选出前 i i i个集装箱,直到不能继续装为止,此时达到最优。

2.2.3图解思路:

假设总载重量 c c c为30,集装箱总共有8个,重量分别是4、10、7、11、3、5、14、2 。
图示:

重量W[i]41071135142
  1. 首先给该列表从小到大排序:
重量W[i]23457101114
  1. 按照贪心策略,每次选重量最小的放入( t m p tmp tmp代表集装箱的重量, a n s ans ans代表已装载的集装箱的个数)

i = 0 i=0 i=0,选择排序后的第1个,装入重量 t m p = 2 tmp=2 tmp=2,不超过载重量30, a n s = 1 ans =1 ans=1
i = 1 i=1 i=1,选择排序后的第2个,装入重量 t m p = 2 + 3 = 5 tmp=2+3=5 tmp=2+3=5,不超过载重量30,$ans =2。
i = 2 i=2 i=2,选择排序后的第3个,装入重量 t m p = 5 + 4 = 9 tmp=5+4=9 tmp=5+4=9,不超过载重量30,$ans =3。
i = 3 i=3 i=3,选择排序后的第4个,装入重量 t m p = 9 + 5 = 14 tmp=9+5=14 tmp=9+5=14,不超过载重量30,$ans =4。
i = 4 i=4 i=4,选择排序后的第5个,装入重量 t m p = 14 + 7 = 21 tmp=14+7=21 tmp=14+7=21,不超过载重量30,$ans =5。
i = 5 i=5 i=5,选择排序后的第6个,装入重量 t m p = 21 + 10 = 31 tmp=21+10=31 tmp=21+10=31,超过载重量30,算法结束。即放入古董的个数为ans=5个。

2.2.4伪代码:

程序=数据结构+算法,需要首先选择数据结构。很显然这里,数据结构数组承载每个集装箱的重量即可。

  1. 数据结构定义
    根据算法设计描述,我们用一维数组存储集装箱的重量:double w[N];//一维数组存储古董的重

  2. 按重量排序可以利用C++中的排序函数sort,对古董的重量进行从小到大(非递减)排序。要使用此函数需引入头文件:
    #include <algorithm>
    语法描述为:
    sort (begin,end)//参数begin和end表示一个范围,分别为待排序数组的首地址和尾地址//sort函数默认为升序
    在本例中只需要调用sort函数对集装箱的重量进行从小到大排序:sort(w,w+n); //按古董重量升序排序

  3. 按照贪心策略找最优解
    首先用变量 a n s ans ans记录已经装载的集装箱个数, t m p tmp tmp代表装载到船上的集装箱的重量,两个变量都初始化为0。然后按照重量从小到大排序,依次检查每个集装箱, t m p tmp tmp加上该集装箱的重量,如果小于等于载重量 c c c,则令 a n s + + ans ++ ans++;否则,退出。

double temp=0.0;int ans=0;/ l tmp为已装载到船上的集装箱重量,ans为已装载的集装箱个数
	for(int i=0;i<n;i++)
	{
		tmp+=w[i];
		if(tmp<=c)
			ans ++;
		else
		break;
	}

2.2.5完整代码:

#include <iostream>
#include <algorithm>
const int N=1000005;
using namespace std;
double w[N];//古董的重量数组
int main ()
{
	double c;
	int n;
	cout<<"请输入载重量c及古董个数n: "<<endl;
	cin>>c>>n;
	cout<<"请输入每个古董的重量,用空格分开:"<<endl;
	for(int i=0;i<n;i++)
	{
		cin>>w[i];//输入每个物品重量
	}
	sort (w, w+n) ; //按古董重量升序排序
	double temp=0.0;
	int ans=0;// tmp为已装载到船上的古董重量,ans为已装载的古董个数
	for(int i=0;i<n;i++)
	{
		temp+=w[i];
		if(temp<=c)
			ans ++;
		else
		break;
	}
	cout<<"能装入的古董最大数量为Ans=";
	cout<<ans<<endl;
	return 0;
}

运行结果:
在这里插入图片描述

2.2.6算法复杂度分析及其改进思路:

未更新

2.3其他可用贪心算法解决的问题(未更新)

其他的可以利用贪心算法解决的问题在此提一嘴,先不详细讲述。

2.3.1背包问题

2.3.2会议安排

2.3.3最短路径

2.3.4哈夫曼编码

2.3.5最小生成树

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请叫我7plus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值