算法-贪心算法知识总结_贪心算法的数学归纳法-程序员宅基地

技术标签: 算法  贪心算法  

目录

1.要素

2.步骤

3.应用实例

4.反例


1.要素

(1)贪心选择性质

贪心选择性质是指,所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。

我们来对贪心算法和动态规划算法做一个对比。

 在动态规划算法中,每步所做的选择往往依赖于相关子问题的解。因而只有在解出相关的子问题后,才能做出选择。

在贪心算法中,仅在当前状态下做出最好选择,即局部最优选择。然后再去解做出这个选择后产生的相应的子问题。

贪心算法所做的贪心选择可以依赖以往所做的选择,但绝不依赖将来所做的选择,也不依赖子问题的解。

由于上述原因,动态规划算法通常以自底向上的方式解决各个子问题,而贪心算法通常以自顶向下的方式进行,以迭代的方式做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为规模更小的子问题。

(2)最优子结构性质

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

2.步骤

(1).把求解的问题分成若干个子问题。
(2).对每一子问题求解,得到子问题的局部最优解。
(3).把子问题的解局部最优解合成原来解问题的一个解。

3.应用实例

这里简要说一下每一个实例的重点

(1)活动安排问题

问题描述:

设有n个活动的集合E={1,2,…, n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有要求使用该资源的起始时间s,和结束时间f,且si<fi。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[s i, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合。
例如:

 计算过程如下:

 对于活动安排问题,贪心算法总能求得的整体最优解,即它最终确定的相容活动集合的规模是最大的,这个结论可以用数学归纳法证明。

事实上,设E={1,2,…,n}为所给定的活动集合。由于E中活动按结束时间的非减序排列,故活动1具有最早完成时间。

首先证明活动安排问题有一个最优解以贪心算法选择开始,即该最优解中包含活动1。

设A ∈E是所给的活动安排问题的一个最优解,且A中活动也按结束时间非减序排列,A中的第一个活动是活动k。若k=1,则A就是一个以贪心选择开始的最优解。若k>l,则设B-A-{k}U{1}。由于fi≤fk且A中活动是相容的,故B中的活动也是相容的。又由于B中活动个数与A中活动个数相同,且A是最优的,故B也是最优的。也就是说,B是以贪心选择活动1开始的最优活动安排。由此可见,总存在以贪心选择开始的最优活动安排方案。
进一步,在做了贪心选择,即选择了活动1后,原问题就简化为对E中所有与活动1相容的活动进行活动安排的子问题。

即若A是原问题的最优解,则A'=A-{1}是活动安排问题E'={i∈E:si≥fi}的最优解。事实上,如果能找到E的一个解B',包含比A'更多的活动,则将活动1加入到B中将产生E的一个解B,它包含比A更多的活动。这与A的最优性矛盾。因此,每步所做的贪心选择都将问题简化为一个更小的与原问题具有相同形式的子问题。

对贪心选择次数用数学归纳法即知,贪心算法 最终产生原问题的最优解。

会场安排问题与活动安排问题类似

会场安排问题是尽可能使用少的会场安排活动,这里附上会场安排问题的核心代码

算法设计分析:

  从文件中获取数据,最先进行排序,按照开始时间由小到大排序,如果开始时间相同就比较结束时间,结束时间越早的就在前面。贪心算法,即尽可能多地在一场会场里安排活动,利用一个整型数组记录当前的活动是否被安排过,从第一个开始安排,只要后面的开始时间大于等于当前的结束时间,就可以安排。

int findmin(int n,int a[][2]){
	int count;
	int i,j;
	int f[n];
	count=0;//cou记录此时安排了多少活动 
	for(i=0;i<n;i++)
	f[i]=0;	
	for(i=0;i<n;i++){
		if(f[i]==0){
			count++;
			int stime=a[i][1];
			for(j=i+1;j<n;j++){
				if(a[j][0]>=stime&&f[j]==0){
					stime=a[j][1];f[j]=1;
				}
			}
		}
	}
	return count;
}

(2)最优装载问题

问题描述: 

算法描述:

最优装载问题与活动安排问题其实是类似的,采用重量轻的优先装载。

贪心选择性质:

设集装箱已依其重量从小到大排序,(x,x2,…,x,)是最优装载问题的一个最优解,设k= min {i|xi=1},如果给定的最优装载问题有解,则1≤k≤n。
(1)当k=1时,(x1,x2,…xn)是一个满足贪心选择性质的最优解。

(2)当k>1时,取y1=1,yk=0,yi=xi;1<i≤n,i≠k,则

因此,(y1,y2,"",yn)是所给最优装载问题的可行解。
   另一方面,由(y1,y2…, yn,)是满足贪心选择性质的最优解。所以,最优
装载问题具有贪心选择性质。

 最优子结构性质

设(x1,x2,…,xn)是最优装载问题的满足贪心选择性质的最优解,则x1=1,(x2,X3,…xn)是轮船载重量为c-w1、待装船集装箱为{2,3,…、n}时相应最优装载问题的最优解。也就是说,最优装载问题具有最优子结构性质。
由最优装载问题的贪心选择性质和最优子结构性质,容易证明算法的正确性。算法 Loading 的主要计算量在于将集装箱依其重量从小到大排序,所以算法所需的计算时间为O(nlogn)。

(3)哈夫曼编码

问题分析:

哈夫曼编码是广泛用于数据文件压缩的十分有效的编码方法。其压缩率通常为20%~90%。哈夫曼编码算法使用字符在文件中出现的频率表来建立一个用0、1串表示各字符的最优表示方式。假设有一个数据文件包含100000个字符,要用压缩的方式存储它。该文件中各字符出现的频率如表4-1所示。文件中共有6个不同字符出现,字符a出现45000次,字符b出现13000次等。
 

前缀码:对每一个字符规定一个0、1串作为其代码,并要求任一字符的代码都不是其他字符代码的前缀。这种编码称为前缀码。
 哈夫曼算法的正确性:

 

最优子结构证明:

核心代码如下

应用优先队列,使算法的时间复杂度优化。

priority_queue<t*,vector<t*>,my>que;//最小堆 
void create(t * temp){
	if(temp->l){//如果有左子树 
		temp->l->code=temp->code+"0";
		create(temp->l);
	}
	if(!(temp->l)&&!(temp->r)){//如果是叶子节点 
		cout<<temp->word<<":"<<temp->code<<endl;
	}
	if(temp->r){
		temp->r->code=temp->code+"1";
		create(temp->r);
	}
}
void createtree(){
	vector<int>ve;
	vector<char>v;
	char w;
	int we;
	int n;
	cin>>n;
	while(n>0){//输入 
		cin>>w>>we;
		ve.push_back(w);
		v.push_back(we);
		n--;
	}
	int length=ve.size(); 
	for(int i=0;i<length;i++){
		t *tt=new t;
		tt->word=ve[i];
		tt->weight=v[i];
		tt->code="";
		tt->l=NULL;
		tt->r=NULL;
		que.push(tt);
	}
	while(que.size()>1){
		t *a,*b;
		a=que.top();
		que.pop();
		b=que.top();
		que.pop();
		t *temp=new t;
		temp->weight=a->weight+b->weight;
		temp->l=a;
		temp->r=b;
		temp->code="";
		temp->word='\0'; 
		que.push(temp);
	}
	create(que.top());
}

(4)单源最短路径

给定一个带权有向图G=(V,E),其中每条边的权是非负实数。另外,给定V中的一个顶点,称为源。现在要计算从源到所有其他各顶点的最短路长度。这里路的长度是指路上各边权之和。这个问题通常称为单源最短路径问题。
算法基本描述:

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

Dijkstra算法是应用贪心算法设计策略的又一个典型例子,所做的贪心选择是从V-S中选择具有最短特殊路径的顶点u,从而确定从源到u的最短路径长度dist[u]。这种贪心选择为什么能导致最优解呢?换句话说,为什么从源到u没有更短的其他路径呢?事实上,如果存在一条从源到u且长度比 dist[u]更短的路,设这条路初次走出S之外到达的顶点为x∈V-S,然后徘徊于S内外若干次,最后离开S到达u。

(7)区间覆盖问题

 分析:从文件中提取数据,先进行排序,从最小的数开始覆盖,即最小数+固定闭区间长度,然后从得到的数后面的最小的数据开始覆盖,这样就可以得到最小的段数。

#include<stdio.h>
#include<stdlib.h>
int n,k;
int a[100];
void getnumber(){
	FILE *fp;
	if((fp=fopen("input2.txt","rt"))==NULL){
		printf("打开失败");
		return;
	}
    fscanf(fp,"%d",&n);
	fscanf(fp,"%d",&k);
	int i;
	for(i=0;i<n;i++){
		fscanf(fp,"%d",&a[i]);
	}
	fclose(fp);	
}
void sort(){
	int i,j,t;
	for(i=0;i<n-1;i++){
		for(j=i+1;j<n;j++){
			if(a[i]>a[j]){
				t=a[i];a[i]=a[j];a[j]=t;
			}
		}
	}
}
void wtout(int count){
	FILE *fp;
	fp=fopen("output2.txt","w");
	if(fp==NULL){
		printf("error");
		return;
	}
	fprintf(fp,"%d",count);
	fclose(fp);
}
void findmin(){
	sort();
	int t,i,j;i=0;
	int count=0;//记录最小段数 
	t=a[i]+k;count++;
	while(t<a[n-1]){
		for(j=i+1;j<n;j++){
			if(a[j]>=t)
			break;
		}
        i=j;
		t=a[j]+k;
		count++;
	}
	wtout(count);
}
int main(){
	getnumber();
	findmin();
	return 0;
}

4.反例

0-1背包问题:

给定n种物品和一个背包。物品i的重量是w,,其价值为v,背包的容量为c。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大?
在选择装入背包的物品时,对每种物品i只有两种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。
此问题的形式化描述是,给定c>0,wi>0,vi>0 (1≤i≤n),要求找出一个n元的0-1向(x1,x2,…,xn),xi∈ {0,1},1≤i≤n,使得,而且达到最大。
背包问题:

与0-1背包问题类似,不同的是在选择物品i (1≤i≤n)装入背包时,可以选择物品i的一部分,而不一定要全部装入背包。

 此问题的形式化描述是,给定c>0, wi>0, vi>0(1≤i≤n),要求找出一个n元向量(x1,x2,…,xn) (0≤xi≤1,1≤i≤n),使得,而且达到最大。

 这两类问题都具有最优子结构性质。对于0-1背包问题,设A是能够装入容量为c的背包的具有最大价值的物品集合,则A=A-{j}是n-1个物品1,2,…,j-1,j+1,…, n可装入容量为c-wj,的背包的具有最大价值的物品集合。对于背包问题,类似地,若它的一个最优解包含物品j,则从该最优解中拿出所含的物品j的那部分重量w,剩余的将是n1个原重物品1,2,…,j-1, j+1,…, n及重为wj-w的物品 j中可装入容量为c-w的背包且具有最大价值的物品。

背包问题可以用贪心算法求解,而0-1背包问题不能用贪心算法求解。

 对于0-1背包问题,贪心选择之所以不能得到最优解是因为,在这种情况下,它无法保证最终能将背包装满,部分闲置的背包空间使每千克背包空间的价值降低了。事实上,在考虑0-1背包问题时,应比较选择该物品和不选择该物品所导致的最终方案,再做出最好选择。

上述主要是结合课本加上自己的分析总结的,希望自己可以坚持学习,收获更多的知识!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_59857406/article/details/121214622

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文