贪心算法 - 常见的问题总结(三)

简介: 贪心算法 - 常见的问题总结(三)

什么是贪心

贪心:贪心在解决问题上是目光短浅的,仅仅根据当前的已知信息就做出选择,并且一旦做了选择,就不再更改

常见的贪心问题

  1. 区间问题
  2. Huffman树
  3. 排序不等式
  4. 绝对值不等式
  5. 推公式

排序不等式

排队打水

典型题例:

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

示例 :

输入:第一行包含两个整数 s 和 t,表示给定线段区间的两个端点。
      第二行包含整数 N,表示给定区间数。
       接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
7
3 6 1 4 2 5 7
输出:
56

思路:左端点排序 + 贪心决策

  1. 先从小到大排序,然后再进行计算
  2. 打水的时间总和为t[1](n1)+t[2](n2)++t[n](nn)=t[i](ni1),下标从零开始

代码:

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int t[N];
int n;
int main() {
    cin >> n;
    for (int i = 0; i < n; i ++ ) scanf("%d", &t[i]);
    sort(t, t + n);
    LL ans = 0;
    for (int i = 0; i < n; i ++) ans += t[i] * (n - i - 1);
    printf("%lld", ans);
    return 0;
} 

绝对值不等式

合并果子

典型题例:

在一条数轴上有 N 家商店,它们的坐标分别为A1AN

现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。

为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小

示例 :

输入:第一行输入整数 N。
      第二行 N 个整数 A1∼AN。
4
6 2 9 1
输出:
12

思路

中位数最优解

相关题目
  1. 一维扩展到二维:3167 星星还是树
  2. 扩展到d维,需要用到退火算法
方法一 O(nlogn)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i ++) scanf("%d", &a[i]);
    sort(a, a + n);
    int ans = 0;
    for (int i = 0; i < n; i ++) ans += abs(a[i] - a[n / 2]);
    printf("%d", ans);
    return 0;
}
方法二O(nlogn)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i ++) scanf("%d", &a[i]);
    sort(a, a + n);
    int ans = 0;
    for (int i = 0; i < n; i ++) ans += a[i] - a[i / 2];  //与abs(a[i] - a[n / 2])等价
    printf("%d", ans);
    return 0;
}
方法三 用到nth_element()函数O(n)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i ++) scanf("%d", &a[i]);
    sort(a, a + n);
    nth_element(a, a + n / 2, a + n);  //
    int ans = 0;
    for (int i = 0; i < n; i ++) ans += abs(a[i] - a[n / 2]);  
    printf("%d", ans);
    return 0;
}

传送门贪心算法 - 常见的问题总结(一)

贪心算法 - 常见的问题总结(二)

充电站

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

相关文章
|
5月前
|
存储 算法 Java
贪心算法和动态规划
贪心算法和动态规划
70 0
|
3月前
|
存储 监控 算法
贪心算法(2024/7/16)
【7月更文挑战第18天】
42 9
|
5月前
|
人工智能 Kubernetes 算法
贪心算法 - 常见的问题总结(二)
贪心算法 - 常见的问题总结(二)
|
5月前
|
人工智能 算法 NoSQL
贪心算法 - 常见的问题总结(一)
贪心算法 - 常见的问题总结(一)
|
11月前
|
算法
算法怎么算:贪心算法
注意:这里是期望最优,而非必定最优。也就是说存在期望落空的情况。而在这种情况下,贪心算法,并非最优解。
60 0
|
12月前
|
算法 Java 调度
贪心算法详解
贪心算法详解
109 0
|
算法
【贪心算法】删数问题
【贪心算法】删数问题
63 0
|
算法
【贪心算法】初步介绍
【贪心算法】初步介绍
74 0
|
人工智能 算法
贪心算法的证明题
贪心算法的证明题
190 0
关于对贪心算法的理解
关于对贪心算法的理解