浅谈贪心算法

简单的说一下贪心算法及其运用

一.基本概念

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部的最优解。

举个例子来说就好比一条路上有两条路,一条路表面轻松,一条路表面艰难,但背后的路却谁也不知道,但这个算法永远都会选择那条轻松的路,而不管后面是怎么走的,简而言之目光短浅。但是目光短浅有的时候也可以求的最优解,这就要看问题本身了。

那么贪心算法在什么时候能够适用呢?

选择贪心算法的问题需要具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。

在选择贪心算法的时候一定需要注意此性质,对于如何处理有后效性的题目,我们以后再做处理。

二.基本思路

1.建立数学模型来描述问题
2.把求解的问题分成若干个子问题
3.对每一个子问题求解,得到子问题的局部最优解
4.把子问题的解局部最优解合成原来解问题的一个解

三.适用问题

贪心算法只适用于从局部最优策略可以产生全局最优策略的题目,当然对于不满足的也可以使用,但不一定能适用!

对于贪心思路的正确性,一般来说都是不好去证明的,很多时候是靠自己感觉而来的。但是贪心思路的反例却比比较好找,找出反例便可以证明其错误性。


相信在阅读完上文的你应该大致了解了一下贪心算法把,接下来来看一道简单的例题,练练手吧!

四.例题

排队接水

有 n 个人在一个水龙头前排队接水,假如每个人接水的时间为 Ti​,请编程找出这 n 个人排队的一种顺序,使得 n 个人的平均等待时间最小。

这是一道非常简单的贪心题,很容易我们就可以知道,因为排队时,越靠近前面的时间计算的次数越多,因此越小的排在前面计算出来的结果就是最小的,所以这道题可以用贪心来进行解决。

(1)将时间从大到小进行排序

(2)将排序后的时间按顺序一次放入每个水龙头的队列中

(3)统计,输出答案

参考代码

#include<bits/stdc++.h>
using namespace std;
struct node{
	int t;
	int num;
}a[1010];
int n;
double ans,sum;
bool cmp(node a,node b){
	return a.t<b.t;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i].t);
		a[i].num=i;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;++i){
		printf("%d ",a[i].num);
		sum+=(n-i)*a[i].t;
	}
	printf("\n");
	ans=sum/n;
	printf("%0.2lf",ans);
	return 0;
} 

另外放上几道练习题,有问题的可以评论或者QQ找我

P1031 均分纸牌 https://www.luogu.com.cn/problem/P1031

P1106 删数问题 https://www.luogu.com.cn/problem/P1106

P1020 导弹拦截 https://www.luogu.com.cn/problem/P1020


贪心比较重要的一点就是要多多练习,掌握一些基本的套路。

遇到问题如果不确定是否使用贪心算法,也可以大胆猜测,然后进行验证。

发表评论