算法模板:经典贪心问题

简介: 算法模板:经典贪心问题


算法模板:经典贪心问题


什么是贪心

贪心的本质是选择每一阶段的局部最优,从而达到全局最优。


这么说有点抽象,来举一个例子:


例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿?


指定每次拿最大的,最终结果就是拿走最大数额的钱。


每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优。


这便是 “贪” 字的由来,考虑局部最优解便是贪心思想的精髓。


其实 此次有一点 标题 党的嫌疑了,因为贪心问题并没有一个通用的模板。


大多数的贪心思想 其实很容易想出来,但难的是证明这样做法的正确性,所以建议读者做贪心问题时,不要从大量时间 来推理解法的正确性,可以换种思路,尝试举出 与解法相悖的反例,如果列举不出反例,则解法应该是没问题的。


区间问题

1.按左端点或右端点排序


2.寻找性质


区间选点

给定 N 个闭区间 [a i,b i],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。


输出选择的点的最小数量。位于区间端点上的点也算作区间内。


输入格式


第一行包含整数 N,表示区间数。接下来 N


行,每行包含两个整数 a i,b i,表示一个区间的两个端点。


输出格式


输出一个整数,表示所需的点的最小数量。


数据范围


1≤N≤105

−109≤a i≤b i≤109


输入样例:


3
-1 1
2 4
3 5


输出样例:


2


题解部分:


贪心思路

1.先将每个区间按右端点从小到大排序

2.然后每次枚举每个区间,当某个区间内已经取了点时,直接跳过即可,否则取每个区间最右端的端点。


image.png


#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
struct PII{
  int l,r;
}s[N];
bool cmp(PII a,PII b)
{
  return a.r<b.r;
}
int main()
{
  int n;
  cin>>n;
  for(int i = 0 ; i < n ; i ++)
  cin>>s[i].l>>s[i].r;
  sort(s,s+n,cmp);
  int ans = 0, ed= -2e9+10;
  for(int i = 0 ; i < n ; i ++)
  if(ed<s[i].l)
  {
    ed=s[i].r;
    ans++;
  }
  cout<<ans;
  return 0;
}


区间数量

给定 N 个闭区间 [a i,b i],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。


输出可选取区间的最大数量。


输出格式


输出一个整数,表示可选取区间的最大数量。


数据范围


1≤N≤105,

−109≤a i≤b i≤109


输入样例:


3
-1 1
2 4
3 5


输出样例:


2


题解部分:

和上一题 可以说是完全一样了


#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
struct PII{
  int l,r;
}s[N];
bool cmp(PII a,PII b)
{
  return a.r<b.r;
}
int main()
{
  int n;
  cin>>n;
  for(int i = 0 ; i < n ; i ++)
  cin>>s[i].l>>s[i].r;
  sort(s,s+n,cmp);
  int ans = 0, ed= -2e9+10;
  for(int i = 0 ; i < n ; i ++)
  if(ed<s[i].l)
  {
    ed=s[i].r;
    ans++;
  }
  cout<<ans;
  return 0;
}


排队接水

n 个人排队到 1 个水龙头处打水,第 i 个人装满水桶所需的时间是 ti,请问如何安排他们的打水顺序才能使所有人的等待时间之和最小 ?


输入样例:


7
3 6 1 4 2 5 7


输出样例:


56


数据范围


1≤n≤10 ^5

1≤t i≤10^4


题解部分:


坑点1 :此题让求解的是等待时间,不算自己接水的时间


坑点2:所有人的等待时间之和,所以需要求解每一个人的等待时间后再累加一遍


坑点3:虽然题目范围 是 10^4 但经过10^5的累加 必然 会爆int 所以需要用 long long


贪心思想:


按等待时间 从小到大排序,用时少的先接水


#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
long long s[N],sum,ans;
int main()
{
  int n,m;
  cin>>n;
  for(int i = 0 ;i < n ; i ++)
  cin>>s[i];
  sort(s,s+n);
  for(int i = 0 ;i < n - 1; i ++)
  {
    sum+=s[i];
    ans+=sum;
  }
  cout<<ans;
  return 0;
}


耍杂技的牛

奶牛们正在试图找到自己在这个堆叠中应该所处的位置顺序。


这 N 头奶牛中的每一头都有着自己的重量 W i 以及自己的强壮程度 S i。


一头牛支撑不住的可能性取决于它头上所有牛的总重量(不包括它自己)减去它的身体强壮程度的值,


现在称该数值为风险值,风险值越大,这只牛撑不住的可能性越高。


您的任务是确定奶牛的排序,使得所有奶牛的风险值中的最大值尽可能的小。


输入格式


第一行输入整数 N,表示奶牛数量。接下来 N行,


每行输入两个整数,表示牛的重量和强壮程度,


第 i 行表示第 i 头牛的重量 W i 以及它的强壮程度 S i。


输出格式


输出一个整数,表示最大风险值的最小可能值。


数据范围


1≤N≤50000

1≤W i≤10,000,

1≤S i≤1,000,000,000


输入样例:


3
10 3
2 5
3 3


输出样例:


2


题解部分:


贪心思路:


我们先分析每头牛的危险值 = 他前面牛的w(重量值)和 - 自身的s(强壮值),


要使每头牛的危险值最小,这显然是与w 和 s同时相关,


所以猜测出一种做法按 每头牛的w + s进行升序排序


然后依次从小到达 按层数由高到低的顺序来计算每头牛的危险值


#include <algorithm>
#include <iostream>
#define x first
#define y second
using namespace std;
typedef pair<int, int> pii;
const int N = 5e4 + 10;
int n;
pii a[N];
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) {
        int w, s;
        cin >> w >> s;
        a[i] = {w + s, w};
    }
    sort(a, a + n);
    int res = -1e9;
    for (int i = 0, sum = 0; i < n; i++) {
        int w = a[i].y, s = a[i].x - w;
        res = max(res, sum - s);
        sum += w;
    }
    cout << res << endl;
    return 0;
}


完结散花

ok以上就是对 经典贪心问题 的全部讲解啦,很感谢你能看到这儿。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。


相关文章
|
6月前
|
算法
Hierholzer算法dfs找欧拉回路模板
Hierholzer算法dfs找欧拉回路模板
68 0
|
存储 算法 决策智能
(万字,细细阅读)竞赛算法入门必经算法模型(附带题目链接和模板)(下)
(万字,细细阅读)竞赛算法入门必经算法模型(附带题目链接和模板)(下)
82 0
|
算法 C++ 容器
(万字,细细阅读)竞赛算法入门必经算法模型(附带题目链接和模板)(上)
(万字,细细阅读)竞赛算法入门必经算法模型(附带题目链接和模板)(上)
49 0
|
算法 C++ 索引
函数模板和类模板 知识点总结 C++程序设计与算法笔记总结(七) 北京大学 郭炜(下)
函数模板和类模板 知识点总结 C++程序设计与算法笔记总结(七) 北京大学 郭炜(下)
47 0
|
3月前
|
算法
【算法】前缀和——二维前缀和模板题
【算法】前缀和——二维前缀和模板题
|
5月前
|
算法 Java 数据处理
Java算法模板 数据流快读
Java算法模板 数据流快读
33 2
|
4月前
|
设计模式 JavaScript 算法
vue2 原理【详解】MVVM、响应式、模板编译、虚拟节点 vDom、diff 算法
vue2 原理【详解】MVVM、响应式、模板编译、虚拟节点 vDom、diff 算法
155 0
|
5月前
|
算法 前端开发 安全
C++算法模板
C++算法模板
31 0
|
6月前
|
算法
简记二分算法模板与代码案例:整数二分和浮点数二分
本文介绍了两种算法模板,分别是整数二分和浮点数二分。
47 0
|
算法 计算机视觉
基于方向编码的模板匹配算法matlab仿真
基于方向编码的模板匹配算法matlab仿真