服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++实现贪心算法的示例详解

C++实现贪心算法的示例详解

2023-02-23 15:37墙缝里的草 C/C++

这篇文章主要通过几个试题为大家详细介绍了C++中贪心算法的实现,文中的示例代码讲解详细,对我们学习贪心算法有一定的帮助,需要的可以参考一下

区间问题

区间选点

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

输出选择的点的最小数量。

位于区间端点上的点也算作区间内。

输入格式

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

接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。

输出格式

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

数据范围

1≤N≤1e5,

−1e9≤ai≤bi≤1e9

先对右端点进行排序,有交集的区间进行右端点的更新,没有交集则点数+1。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<bits/stdc++.h>
using namespace std;
 
const int N=1e5+10;
struct node{
    int a,b;
    bool operator<(const node&w)const {
        return b<w.b;}
}range[N];
 
int main(){
    int n;
    cin>>n;
    int a,b;
    for(int i=0;i<n;i++){
        cin>>a>>b;
        range[i]={a,b};
    }
    sort(range, range+n);
    int s=-2e9,cnt=0;
    for(int i=0;i<n;i++){
        if(s<range[i].a){
            cnt++;
            s=range[i].b;
        }
    }
    cout<<cnt;
    return 0;
}

最大不相交区间数量

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

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

输入格式

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

接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。

输出格式

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

数据范围

1≤N≤1e5,

−1e9≤ai≤bi≤1e9

先对右端点进行排序,有交集的区间进行右端点的更新,没有交集则点数+1。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
 
struct node{
    int a,b;
    bool operator<(const node&w)const{
        return b<w.b;
    }
}range[N];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        int a,b;
        cin>>a>>b;
        range[i]={a,b};
    }
    int res=0,s=-2e9;
    sort(range,range+n);
    for(int i=0;i<n;i++){
        if(range[i].a>s){
            s=range[i].b;
            res++;
        }
    }
    cout<<res;
    return 0;
    
}

区间分组

给定 N 个闭区间 [ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。

输出最小组数。

输入格式

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

接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。

输出格式

输出一个整数,表示最小组数。

数据范围

1≤N≤1e5,

−1e9≤ai≤bi≤1e9

先区分左右端点进行排序,再遍历取左右 端点未抵消的最大值。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<bits/stdc++.h>
 
using namespace std;
 
const int N = 100010;
 
int n;
int b[2 * N], idx;
 
int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        int l, r;
        cin >> l >> r;
        b[idx++] = l * 2;
        b[idx++] = r * 2 + 1;//用奇偶性区分左右端点
    }
    sort(b, b + idx);
    int res = 1, t = 0;
    for (int i = 0; i < idx; i++) {
        if (b[i] % 2 == 0)t++;
        else t--;
        res = max(res, t);
    }
    cout << res;
    return 0;
}

优先队列做法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
struct Range {
    int l, r;
    bool operator <(const  Range& w)const {
        return l < w.l;
    }
}range[N];
int n;
int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        int l, r;
        cin >> l >> r;
        range[i] = { l,r };}
    sort(range, range + n);
    int res = 0,ed=-2e9;
    
    priority_queue<int, vector<int>, greater<int>>heap;
    for (int i = 0; i < n; i++) {
        auto r = range[i];
        if (heap.empty() || heap.top() >= r.l)heap.push(r.r);
        else {
            int t = heap.top();
            heap.pop();
            heap.push(r.r);
        }
    }
    cout << heap.size();
    return 0;
}

区间覆盖

给定 N 个闭区间 [ai,bi] 以及一个线段区间 [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。

输出最少区间数,如果无法完全覆盖则输出 −1。

输入格式

第一行包含两个整数 s 和 t,表示给定线段区间的两个端点。

第二行包含整数 N,表示给定区间数。

接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。

输出格式

输出一个整数,表示所需最少区间数。

如果无解,则输出 −1。

数据范围

1≤N≤1e5,

−1e9≤ai≤bi≤1e9,

−1e9≤s≤t≤1e9

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include<bits/stdc++.h>
 
using namespace std;
 
const int N = 100010;
struct  Range {
    int l, r;
    bool operator <(const Range& w)const {
        return l < w.l;
    }
}range[N];
 
int main() {
    int n;
    int st, ed;
    cin >> st >> ed;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int l, r;
        cin >> l >> r;
        range[i] = { l,r };
 
    }
    sort(range, range + n);
    int res = 0;
    bool sc = false;
    for (int i = 0; i < n; i++) {
        int j = i, r = -2e9;
        while (j < n && range[j].l <= st) {
            r = max(r, range[j].r);
            j++;
        }
        if (r < st) {
            res = -1;
            break;
        }
        res++;
        if (r >= ed) {
            sc = true;
            break;
        }
        i = j-1;
        st = r;
    }
    if (!sc)cout << -1;
    else cout << res;
    return 0;
}

Huffman树

合并果子

在一个果园里,达达已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。

达达决定把所有的果子合成一堆。

每一次合并,达达可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。

可以看出,所有的果子经过 n−1 次合并之后,就只剩下一堆了。

达达在合并果子时总共消耗的体力等于每次合并所耗体力之和。

因为还要花大力气把这些果子搬回家,所以达达在合并果子时要尽可能地节省体力。

假定每个果子重量都为 1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使达达耗费的体力最少,并输出这个最小的体力耗费值。

例如有 3 种果子,数目依次为 1,2,9。

可以先将 1、2 堆合并,新堆数目为 3,耗费体力为 3。

接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 12,耗费体力为 12。

所以达达总共耗费体力=3+12=15。

可以证明 15 为最小的体力耗费值。

输入格式

输入包括两行,第一行是一个整数 n,表示果子的种类数。

第二行包含 n 个整数,用空格分隔,第 i 个整数 ai 是第 i 种果子的数目。

输出格式

输出包括一行,这一行只包含一个整数,也就是最小的体力耗费值。

输入数据保证这个值小于 231。

数据范围

1≤n≤10000,

1≤ai≤20000

只需要用优先队列先取出两个,再插入一个,直至最后剩下一个。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
#include<algorithm>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
 
int main() {
    int n;
    cin>>n;
    priority_queue<int, vector<int>, greater<int>>heap;
 
    while (n--) {
        int x;
        cin >> x;
        heap.push(x);
    }
    int res = 0;
    while (heap.size() > 1) {
        int a = heap.top();
        heap.pop();
        int b = heap.top();
        heap.pop();
        int c = a + b;
        heap.push(c);
        res += c;
    }
    cout << res;
    return 0;
}

排序不等式

排队打水

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

输入格式

第一行包含整数 n。

第二行包含 n 个整数,其中第 i 个整数表示第 i 个人装满水桶所花费的时间 ti。

输出格式

输出一个整数,表示最小的等待时间之和。

数据范围

1≤n≤1e5,

1≤ti≤1e4

值正序,下标倒序相乘得到最小值

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<bits/stdc++.h>
using namespace std;
 
const int N = 100010;
int a[N];
int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    sort(a, a + n);
    int x=n;
    long long res=0;
    for (int i = 0; i < n; i++) {
        res += a[i] * (x - 1);
        x--;
    }
    cout << res;
    return 0;
}

绝对值不等式

货舱选址

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

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

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

输入格式

第一行输入整数 N。

第二行 N 个整数 A1∼AN。

输出格式

输出一个整数,表示距离之和的最小值。

数据范围

1≤N≤100000,

0≤Ai≤40000

只需统计各点到中位数的距离之和。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <bits/stdc++.h>
using namespace std;
const int N=100100;
int a[N],n,i,ans,sum;
int main()
{
    cin>>n;
    for (i=1;i<=n;i++)
        cin>>a[i];
    sort(a+1,a+1+n);//排序
    int sm=a[n/2+1];//中位数
    for (i=1;i<=n;i++)
        ans=ans+abs(a[i]-sm);//统计和中位数之间的差
    cout<<ans;
    return 0;
}

以上就是C++实现贪心算法的示例详解的详细内容,更多关于C++ 贪心算法的资料请关注服务器之家其它相关文章!

原文链接:https://blog.csdn.net/weixin_52465909/article/details/125630088

延伸 · 阅读

精彩推荐
  • C/C++c语言文件读写示例(c语言文件操作)

    c语言文件读写示例(c语言文件操作)

    这篇文章主要介绍了c语言文件读写示例(c语言文件操作),需要的朋友可以参考下...

    C语言教程网5682021-01-14
  • C/C++floyd算法实现思路及实例代码

    floyd算法实现思路及实例代码

    这篇文章主要介绍了floyd算法实现思路及实例代码,有需要的朋友可以参考一下...

    C语言教程网9412021-01-13
  • C/C++C++简单集合类的实现方法

    C++简单集合类的实现方法

    如何使用C++实现一个简单的集合类,这篇文章主要介绍了C++简单集合类的实现方法,感兴趣的小伙伴们可以参考一下...

    C++教程网8772021-04-09
  • C/C++C语言实现学生宿舍信息管理系统课程设计

    C语言实现学生宿舍信息管理系统课程设计

    这篇文章主要为大家详细介绍了C语言实现学生宿舍信息管理系统课程设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参...

    tan-121011142022-10-21
  • C/C++C语言之qsort函数详解

    C语言之qsort函数详解

    这篇文章主要介绍了C语言中qsort函数的用法实例详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下...

    可爱的乐乐哥哥11432021-12-22
  • C/C++C++代码实现逆波兰式

    C++代码实现逆波兰式

    这篇文章主要为大家详细介绍了C++代码实现逆波兰式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    ronnie885976552021-09-30
  • C/C++C++操作json文件以及jsoncpp配置详解

    C++操作json文件以及jsoncpp配置详解

    这篇文章主要给大家介绍了关于C++操作json文件以及jsoncpp配置的相关资料,文中通过实例代码及图片介绍的非常详细,需要的朋友可以参考下...

    水亦心8942021-11-11
  • C/C++C++读写INI配置文件的类实例

    C++读写INI配置文件的类实例

    这篇文章主要介绍了C++读写INI配置文件的类,实例分析了C++操作ini配置文件的相关技巧,需要的朋友可以参考下...

    红薯7122021-02-27