算法笔记4——贪心算法

一、要点

贪心算法的基本要素

1、贪心选择性质

整体最优解是一系列局部最优解的选择,同时也是贪心与动态规划最主要的区别。
贪心自上而下解决问题,动态规划自下而上解决问题。
动态规划要求解所有子问题,而贪心只需要局部最优解。

2、最优子结构性

当一个问题的最优解包含其子问题的最优解时,我们称问题具有最优子结构性。

3、只有一个FOR循环

二、问题

活动安排问题

问题:设有一系列活动需要使用一个报告厅,而在同一时间内,只有一个活动可以使用这个报告厅。每个活动的开始时间和结束时间已知,问如何安排活动,使报告厅的利用率最大化?
核心思想:我们开两个数组s[],e[]分别存放活动的开始时间和结束时间。数组的排列顺序按照活动的结束时间排序,即结束时间早的排在前面,结束时间晚的排在后面。一开始,我们安排活动1使用报告厅,然后依次比较剩下活动的开始时间,开始时间在活动1的结束时间之前的活动直接PASS。如果开始时间在活动1结束时间之后,就将它安排成下一个,让后再用它的结束时间和后面的活动进行比较。
整个过程就是这么简单,这里有小伙伴可能就会问了,你这样安排一定可以保证是最优的吗?
事实上,贪心算法往往只关心当前最优解,而不考虑整体最优,所以很多情况下,使用贪心算法都不能保证得到的是全局的最优解,但对于活动安排问题,我们使用贪心法一定可以得到全局最优解,这一点可以用数学归纳法证明,这里就不做进一步的证明了。

//s[]存开始时间,e[]存结束时间,A[]存安排的活动
//e[]按照由小到大排列,先结束的排在前面
void GreedySelector(int n ,type s[] ,type e[] ,bool A[] )
{
	A[I]=true;//活动1默认安排
	int j =1;
	for(int i =1;i<=n;i++)
	{
		if(s[i]>=e[j])//如果下一个活动的开始时间晚于当前活动的结束时间,将下一个活动置为true;
		{
			A[i]=true;
			j=i;
		}
		else
		A[i]=false;
	}
}

背包问题

贪心法其实并不能够解决0-1背包问题,因为在0-1背包问题中,物品是不可拆分的,如果我们假设物品可以拆分,即可以装入1/2个物品或者1/4个物品等,那么问题就可以用贪心法来解决了。
贪心法解决背包问题的思路很简单,我们用物品价值/物品重量,得到物品的单位价值,然后按单位价值排序,再往里面按顺序装就行了,如果最后一个物品装不下了,就把物品拆分,把背包的空装满就行。

public class test{
	
	public void tanxin()
	{
		float rest= bag;
		int j=0;
		float b=0;
		for(int i=2;i>=0;i--)
		{
			if(goods[i].weight<=rest)
			{
				goods[i].bn=goods[i].weight;
				goods[i].an=goods[i].value;
				rest=rest-goods[i].weight;
				b=b+goods[i].value;
				j++;
			}
			
			else if(rest>0){
	            float a =(float)rest/goods[i].weight;
	            goods[i].an=goods[i].value*a;
	            goods[i].bn=goods[i].weight*a;
	            b=b+(goods[i].value*a);
	            rest=0;
			}
		}
		
		

单源最短路径(DijKstra算法)

大名鼎鼎的DijKstra算法其实就是单源最短路径问题的贪心法解法。其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其他顶点之间的最短路径长度。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
算法复杂度为:n平方

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值