C++:第八讲贪心算法1

Everyday English

Four short words sum up what has lifted most successful individuals above the crowd: a little bit more. 成功的秘诀就是四个简单的字:多一点点。

前言

今天给大家讲一下贪心算法1。

贪心算法思想

        贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。在实际生活中,我们常常需要求解一些问题的最优解问题。贪心算法就是求解这一类问题的一种算法。它总是不断贪心地选取当前最优策略的算法。贪心算法的基本思想就是通过局部最优从而得到全局最优的解决方案。
        所有能使用贪心算法解决的问题,其实都是可以在数学上严格证明的,但是在程序设计
竞赛中,快速解题是非常重要的。当直觉上可以使用贪心算法,无需进行严格的证明。但这
种直觉的培养需要大量地做题来积累。当你想出一个算法,但却无法 AC,首先需要弄清楚
是算法有问题,还是算法的实现有问题。如果是算法本身有问题,可以尝试自行构造一些数
据,使得算法出现错误(称作 hack),从而进一步理解贪心算法为何出错。

该算法存在的问题
1.不能保证求得的最后解是最佳的
2.不能用来求最大值或最小值的问题
3.只能求满足某些约束条件的可行解的范围

例题

题目描述

洛谷陶陶摘苹果(升级版)

 题目描述

又是一年秋季时,陶陶家的苹果树结了 n 个果子。陶陶又跑去摘苹果,这次他有一个 a 公分的椅子。当他手够不着时,他会站到椅子上再试试。

这次与 NOIp2005 普及组第一题不同的是:陶陶之前搬凳子,力气只剩下 s 了。当然,每次摘苹果时都要用一定的力气。陶陶想知道在 s<0 之前最多能摘到多少个苹果。

现在已知 n个苹果到达地上的高度 x_i,椅子的高度 a,陶陶手伸直的最大长度 b,陶陶所剩的力气 s,陶陶摘一个苹果需要的力气 y_i,求陶陶最多能摘到多少个苹果。

输入格式

第 1 行:两个数 苹果数 n,力气 s。

第 2 行:两个数 椅子的高度 a,陶陶手伸直的最大长度 $b$。

第 3行~第 3+n-1 行:每行两个数 苹果高度 x_i,摘这个苹果需要的力气y_i。

输出格式

只有一个整数,表示陶陶最多能摘到的苹果数。

样例输入 #1
8 15
20 130
120 3
150 2
110 7
180 1
50 8
200 0
140 3
120 2
 样例输出 #1

4

思路点拨&要点

1.将所有能摘的到的苹果按照所需体力值从小到大排序。
2.贪心的按体力值从小到大摘取每一个苹果,直到体力值不够摘下一个苹果为止。

AC:

#include
using namespace std;
const int maxn=1e4+3;
int n,s,a,b,m,c[maxn],ans;
int main(){
        cin>>n>>s>>a>>b; 
        for (int i=1;i<=n;i++){
                int x,y; cin >> x >> y;
                if (x<=a+b) c[++m]=y;
        }
        sort(c+1,c+m+1);
        for (int i=1;i<=m;i++){
                if (s>=c[i]) s-=c[i])ans++;
        }
        cout << ans << endl;

        return 0;
}


以上就是用了贪心算法来解决陶陶摘苹果(升级版)

洛谷小课堂

[NOIP2007 普及组] 纪念品分组

题目描述

元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得 的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品, 并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。

你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。

 输入格式

共 n+2 行:

第一行包括一个整数 w,为每组纪念品价格之和的上限。

第二行为一个整数 n,表示购来的纪念品的总件数 $G$。

第 3\sim n+2 行每行包含一个正整数 P_i 表示所对应纪念品的价格。

 输出格式

一个整数,即最少的分组数目。

 样例输入 #1
100 

90 
20 
20 
30 
50 
60 
70 
80 
90

样例输出 #1
6

思路点拨

1.我们希望尽可能地多的将2个纪念品放在一组,答案为 减去"2个纪念品一组"的组数。
2.将所有纪念品按价格排序。
3.从价格最小的纪念品开始贪心,因为与它匹配的纪念品价格越大越好。
4.用一个指针记录与当前纪念品匹配的纪念品位置,不断左移指针,直到不能匹配为止。

AC:

#include
using namespace std;
const int maxn=3e4+3;
int n,a[maxn],w,ans;
int main(){
    cin >> w >> n;
    for (int i=1;i<=n;i++) cin >> a[i];
    sort(a+1,a+n+1); ans=n;
    int r=n;
    for (int i=1;ii&&a[i]+a[r]>w) r--;
            if (r>i&&a[i]+a[r]<=w) ans--,r--;
    }
    cout << ans << endl;
	return 0;
}

结尾

本篇文章共2150字,博主还是一名小学生,真的尽力了。

如果你能支持一下我,我十分感谢!!!

最后认识一下,我是爱编程的喷火龙廖,我们有缘再见!

你可能感兴趣的:(c++,算法,数据结构)