算法学习20:贪心01

算法学习20:贪心01



前言

在这里插入图片描述


提示:以下是本篇文章正文内容:

一、区间问题

1. 区间选点:(右端点)

在这里插入图片描述



在这里插入图片描述



在这里插入图片描述



在这里插入图片描述



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

输入:
第一行包含N
接下来N行,每行包含2个整数ai, bi,表示一个区间的两个端点

输出:所需点的最小数量

数据范围:1<= N <= 10^5  -10^9 <= ai <= bi <= 10^9
*/
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
// 按右端点排序 
struct Range
{
	int l, r;
	bool operator< (const Range &W) const
	{
		return r < W.r;
	}
}range[N];

int main()
{
	scanf("%d", &n);
	for(int i = 0; i < n; i ++)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		range[i] = {l, r};		
	}
	
	// 1.按右端点排序 
	sort(range, range + n);
	
	int res = 0, ed = -2e9;
	for(int i = 0; i < n; i ++)
		// 当前区间的左端点 大于 维护的右端点 
		if(range[i].l > ed)
		{
			res ++;
			ed = range[i].r;// 更新 
		}
	
	printf("%d\n", res);
	return 0;
 } 

在这里插入图片描述



2. 最大不相交区间数量

在这里插入图片描述



在这里插入图片描述



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

输入:
第一行包含N,表示区间个数
接下来N行,每行包含2个整数ai, bi,表示一个区间的2个端点。

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

数据范围:1<= N <= 10^5  -10^9 <= ai<=bi <= 10^9
*/
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
struct Range
{
	int l, r;
	bool operator< (const Range &W)const
	{
		return r < W.r;
	}
}range[N];


int main()
{
	scanf("%d", &n);
	for(int i = 0; i < n; i ++)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		range[i] = {l, r};
	}
	// 按照右端点,从小到大排序 
	sort(range, range + n);
	
	int res = 0, ed = -2e9;
	for(int i = 0; i < n; i ++)
		// 当前区间的左端点 大于 维护的右端点 
		if(ed < range[i].l)
		{
			res ++;
			ed = range[i].r;
		 } 
	
	printf("%d\n", res);
	return 0;
 } 

在这里插入图片描述



3. 区间分组

在这里插入图片描述



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

输入:
第一行包含N,表示区间数
接下来N行,包含2个整数ai,bi,表示一个区间的左右端点

输出:最小组数

数据范围:1<= N <= 10^5  -10^9<= ai<=bi <= 10^9
*/
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 100010;

int n;
// 按照区间左端点排序 
struct Range
{
	int l, r;
	bool operator< (const Range &W)const
	{
		return l < W.l;
	}
}range[N];


int main()
{
	scanf("%d", &n);
	for(int i = 0; i < n; i ++)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		range[i] = {l, r};
	 } 
	// 按照左端点排序 
	sort(range, range + n);
	
	// 创建一个 小根堆 (堆顶元素是最小的) 
	priority_queue< int, vector<int>, greater<int> > heap;
	for(int i = 0; i < n; i ++)
	{
		auto e = range[i];
		// heap为空 或  所有组的右端点的最小值Max_r > e.l
		if(heap.empty() || heap.top() >= e.l) heap.push(e.r);//  开新的组 
		else
		{
			int t = heap.top();// 有什么用??? (好像没有用到!) 
			heap.pop();// 去堆顶 
			heap.push(e.r);// 更新当前组 
		}
	 } 
	
	printf("%d\n", heap.size());
	return 0;
}

在这里插入图片描述



4. 区间覆盖:

在这里插入图片描述



/*
给定N个闭区间[ai, bi]以及一个线段区间[s,t],请你选择尽量少的区间,将指定线段区间完全覆盖
输出最少的区间数,如果无法完全覆盖则输出-1

输入:
第一行包含2个整数s和t,表示给定线段区间的2个端点
第二行包含整数N
接下来N行,每行包含2个整数ai,bi,表示一个区间的2个端点

输出:
输入一个整数,表示所需要的最少区间数
如果无解,则输出-1

数据范围:
1<= N <= 10^5
-10^9 <= ai, bi <= 10^9
-10^9 <= s, t <= 10^9
*/
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
// 按照左端点排序 
struct Range
{
	int l, r;
	bool operator< (const Range &W)const
	{
		return l < W.l;
	}
 } range[N];
  

int main()
{
	int st, ed;
	scanf("%d%d", &st, &ed);
	scanf("%d", &n);
	for(int i = 0; i < n; i ++)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		range[i] = {l, r};
	}
	// 按左端点排序 
	sort(range, range + n);
	
	int res = 0;
	bool success = false;// 标志 
	for(int i = 0; i < n; i ++)
	{
		int j = i, r = -2e9;
		// 覆盖st的区间,选择右端点最大的那个 
		while(j < n && range[j].l <= st)
		{
			r = max(r, range[j].r);
			j ++;
		}
		
		// 如果没有,直接跳出 
		if(r < st)
		{
			res = -1;
			break;
		}
		
		res ++;
		if(r >= ed)
		{
			success = true;
			break;
		}
		
		st = r;
		i = j - 1;
	}
	
	if(!success) res = -1;// 这句有的重复了??? 
	printf("%d\n", res);
	return 0;
}

在这里插入图片描述



二、哈夫曼树

1. 合并果子

在这里插入图片描述



在这里插入图片描述



/*
有堆果子,要把所有的果子合成一堆。
每一次合并,可以把2堆果子合并到一起,消耗的体力等于2堆果子的重量之和。
可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。
总共消耗的体力等于每次消耗体力之和。
假定每个果子的重量都为1,请你设计出合并的次序方案,是耗费的体力最小,输出这个最小的体力耗费值。

输入:
第一行包含整数n,表示有几堆果子
第二行包含n个整数,第i个整数ai是第i堆果子的数量

输出:
最小的体力耗费值,保证这个值小于2^31

数据范围:
1<=n <= 1000
1 <= ai <= 20000
*/
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;


int main() 
{
	int n;
	scanf("%d", &n);
	// 定义小顶堆,要加2个参数,规定是这样写的 (也叫优先队列) 
	priority_queue< int, vector<int>, greater<int> > heap;
	while(n --)
	{
		int x;
		scanf("%d", &x);
		heap.push(x);
	 } 
	
	int res = 0;
	// 只要heap里面的个数 大于2 
	while(heap.size() > 1)
	{
		// 弹出最小的2个,压入a+b的和 
		int a = heap.top(); heap.pop();
		int b = heap.top(); heap.pop();
		res += a + b;
		heap.push(a + b);
	}
	
	printf("%d", res);
	return 0;
}

在这里插入图片描述


总结

提示:这里对文章进行总结:

💕💕💕

相关推荐

  1. Day27- 贪心算法part01

    2024-04-20 18:16:04       30 阅读
  2. Day29- 贪心算法part03

    2024-04-20 18:16:04       40 阅读
  3. 贪心算法day01

    2024-04-20 18:16:04       34 阅读
  4. 贪心算法part01 算法

    2024-04-20 18:16:04       36 阅读
  5. 贪心算法day05

    2024-04-20 18:16:04       33 阅读
  6. 贪心算法Day02

    2024-04-20 18:16:04       41 阅读
  7. 贪心算法day03

    2024-04-20 18:16:04       33 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-20 18:16:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-20 18:16:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-20 18:16:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-20 18:16:04       18 阅读

热门阅读

  1. 总结批量创建文件夹及文件重命名、移动的方法

    2024-04-20 18:16:04       12 阅读
  2. datalist 是什么?以及作用是什么?

    2024-04-20 18:16:04       18 阅读
  3. 实体类List重复校验

    2024-04-20 18:16:04       15 阅读
  4. go热更新配置文件

    2024-04-20 18:16:04       12 阅读
  5. 100个Go语言典型错误

    2024-04-20 18:16:04       13 阅读
  6. scilab笔记

    2024-04-20 18:16:04       12 阅读
  7. 图搜索算法详解

    2024-04-20 18:16:04       13 阅读
  8. 基于simulink的配网自动化仿真

    2024-04-20 18:16:04       14 阅读