贪心

                                                贪心

先奉上一段千古名言:                

模拟只会猜题意,

贪心只能过样例,

数学上来先打表,

DP一般看规律。

组合数学靠运气,

计算几何瞎暴力,

图论一顿套模板,

数论只会GCD。

 

好了言归正传,我们来讲一下贪心的概念:

         贪心是一种策略,一种思想。在对问题进行求解时,总是能作出当前看来最好的选择,通过作出局部最优选择达到全局最优选择

         贪心没有固定的算法框架,它在不同的题目中出现的形式都是不一样的。但是它算法设计的关键是贪心策略的选择。也就是说想要贪心,你就得从题目的某个条件为基础,根据这个条件选择如何能得到局部的最优解。贪心在大多数情况下都是能将题目AC的,但是如果遇到了某种问题,就能在不是完全AC的情况下得到最高的分数,这就是“贪心”策略名字的由来,所以说贪心只能过样例

解题思路:

   1、看看这题是否适合贪心(如果这道题不能用贪心的话,你还可以选择打表。。。

   2、选择贪心的标准(这个是关键)。

   3、根据标准把求解的问题分成若干个子问题。

   4、对每一个子问题求解,得到子问题的局部最优解。

   5、把每个子问题的解局部最优解合成原来问题的一个解,也就是全局最优解。

 

那么接下来我们看例题:

                                           纪念品分组

由于本蒟蒻太懒,懒得复制粘贴,题目与代码详情请见https://blog.csdn.net/j1124911538/article/details/81125377。

思路:尽量多的两两结合成一组,这就是本题的策略。排序,两端的物品结合,如果  不能结合,大的就单独一组,如果能结合,就合为一组继续。

                                                                                      

                                           游荡的奶牛 

 题目与代码详情请见https://blog.csdn.net/j1124911538/article/details/81121390。

 思路:右端点从小到大排,这道题跟长度没关系,以当前线段为基准,如果下一条线与它相交,那么s--(s表示最多牛同时吃草的数量),因为下一条线的右端点更靠右,可能会覆盖更多线段。如果没有相交,以下一条线作为新基准。右端点大的与别的线段冲突的概率大,只要和B有冲突的,必然和A有冲突,所以必然不要A。这是反正法。4

算法流程:

结构体声明一个线段:左端点,右端点

右端点排序

一个for 循环完成线段的选择

 

如图所示:

贪心_第1张图片

良心代码                                           

                                            智力大冲浪

题目与代码详情请见https://blog.csdn.net/j1124911538/article/details/78966990。

规则:在最晚的时刻完成,这样能保证更多的游戏不冲突。

思路:考虑贪心策略,这个题我们按价值从大到小排序,然后时间从后往前找,从第n个时间段开始,如果某一个任务结束时间在n之后,我们就可以用,然后打上标记,最后检查有多少个元素没打上标记,然后求总价值即可。

                                                                                           

                                               三值排序

题目与代码详情请https://blog.csdn.net/j1124911538/article/details/81133700。

思路:

将序列排序后,有值为1、2、3共有三个值段;另找三个变量x,y,z。x为在值段1中不是1的个数;y为在值段2中值为3的个数;z为在值段3中值为2的个数。所以最小交换次数为x+max(y,z)。

找出排序之后是1一开始不是1的个数,排序之后是2一开始是3的个数,与排序之后是3一开始是2的个数,然后比较排序之后是2一开始是3的个数,与排序之后是3一开始是2的个数,求出最大值,并把它与排序之后是1一开始不是1的个数相加,就求出最少交换的次数了。

 

                                               删数问题

题目与代码详情请见https://blog.csdn.net/j1124911538/article/details/81140976。

思路:贪心法求解:删k个数符的全局最优解,包含了删除1个数符的子问题的最优解。 以字符串形式输入s,使用尽可能逼近目标的贪心法来逐一删去其中的k个数符,每一步总是选择一个能使剩下的数最小的数符删去。靠前的局部最大值删除,越是高位删除,保留的数的数值越小。

 

                                                   潜水

哎,终于有道我没打过博客的题了。。。

贪心_第2张图片

题目描述

在马其顿王国的ohide湖里举行了一次潜水比赛。其中一个项目是从高山上跳下水,再潜水达到终点。这是一个团体项目,一支队伍由n人组成。在潜水时必须使用氧气瓶,但是每只队伍只有一个氧气瓶。最多两人同时使用一个氧气瓶,但此时两人必须同步游泳,因此两人达到终点的时间等于较慢的一个人单独游到终点所需要的时间。好在大家都很友好,因此任何两个人后都愿意一起游水。安排一种潜水的策略,使得最后一名选手尽量早的达到终点。

输入格式

第一行:队伍的人数n(<=1000)。 下面是n行,每行1个数,分别是n个潜水所用的时间ti(<=1000)。

输出格式

1个整数,表示最少用的时间。

样例数据

input

3
1 3 4

output

8
{4+1+3}
氧气瓶还必须潜水送回来^-^

 思路:首先我么应该思考的是,该怎样才能把所有人运到终点,并且耗时最少。

每个阶段运两个人过去有两种贪心原则

1.用耗时最少的每次运一个走

2.用耗时最少的和次少的分两次次运走耗时最多的两个走

每次在两种贪心原则中,选择最优的。这道题的策略就是两种贪心优中选优。

那么代码如下:

#include
using namespace std;
int main()
{
	int n,a[1010]={};
	int s=0;
	cin>>n;
	for (int i=1;i<=n;i++)
	cin>>a[i];
	sort(a+1,a+n+1);
	while (n>=4)
	{
		s=s+min(a[1]*2+a[n]+a[n-1],a[1]+a[2]*2+a[n]);
		n=n-2;
	}
	if (n==3)
	{
		s=s+a[1]+a[n]+a[n-1]; 
	}
	if (n==2)
	{
		s=s+a[n];
	}
	cout<

 

 当然贪心的范围可不止这几道题,连数字三角形和01背包这种DP都可以用贪心来做。

 贪心_第3张图片

 但在这里我就不多说了,在后面的DP总结中会讲到这两题。(好吧其实是因为我太懒

 

贪心总结:

贪心的策略就是每步选择最优,导致全局最优。

但是,贪心的策略必须要证明正确。

图论中有很多贪心的算法

错误的贪心也很多。(然并卵,你开心就行)

 

最后再重复一句千古名言:

贪心只能过样例,计算几何瞎暴力。

你可能感兴趣的:(算法分析)