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

 更新时间:2022年07月06日 08:17:31   作者:墙缝里的草  
这篇文章主要通过几个试题为大家详细介绍了C++中贪心算法的实现,文中的示例代码讲解详细,对我们学习贪心算法有一定的帮助,需要的可以参考一下

区间问题

区间选点

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

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

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

输入格式

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

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

输出格式

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

数据范围

1≤N≤1e5,

−1e9≤ai≤bi≤1e9

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

#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。

#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

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

#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;
}

优先队列做法。

#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

#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

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

#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

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

#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

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

#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++ 贪心算法的资料请关注脚本之家其它相关文章!

相关文章

  • QT结合百度Ai实现车牌识别

    QT结合百度Ai实现车牌识别

    当下的人工智能势头很盛,本文主要介绍了QT结合百度Ai实现车牌识别,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-03-03
  • C++野指针和悬空指针的实现方法

    C++野指针和悬空指针的实现方法

    野指针和悬空指针是指针中常见的两个概念,本文详细的介绍了这两种的使用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • C++基于CMD命令行实现扫雷小游戏

    C++基于CMD命令行实现扫雷小游戏

    这篇文章主要为大家详细介绍了C++基于CMD命令行实现扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • C++详解如何实现单链表

    C++详解如何实现单链表

    线性表的链式存储又称为单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素。本文将用C++实现单链表,需要的可以参考一下
    2022-06-06
  • 一文带你简单了解c++正则表达式

    一文带你简单了解c++正则表达式

    正则表达式在匹配字符串,验证输入合法性时经常用到.C++ 11标准库中已经支持了正则表达式,下面这篇文章主要给大家介绍了关于c++正则表达式的相关资料,需要的朋友可以参考下
    2023-04-04
  • C语言 链式二叉树结构详解原理

    C语言 链式二叉树结构详解原理

    二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址
    2021-11-11
  • C++ 指向类成员的指针

    C++ 指向类成员的指针

    指向类成员的指针总的来讲可以分为两大类四小类(指向数据成员还是成员函数,指向普通成员还是静态成员)
    2020-03-03
  • C++使用智能指针实现模板形式的单例类

    C++使用智能指针实现模板形式的单例类

    这篇文章主要为大家详细介绍了C++使用了智能指针实现模板形式的单例类,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • 纯C语言:分治假币问题源码分享

    纯C语言:分治假币问题源码分享

    这篇文章主要介绍了纯C语言:分治假币问题源码,有需要的朋友可以参考一下
    2014-01-01
  • C语言实现生成新春福字的示例详解

    C语言实现生成新春福字的示例详解

    这篇文章主要介绍了如何利用C语言实现生成各个字体的新春福字,再也不用担心支付宝扫福找不到图片了,感兴趣的同学可以跟随小编学习一下
    2022-01-01

最新评论