算法基础课 贪心算法模板题笔记

AcWing算法基础课 贪心算法模板题笔记

贪心得到的答案 >= 最优解
贪心得到的答案 <= 最优解

局部最优 -> 全局最优

文章目录

  • 1 区间问题
    • 例1:区间选点
    • 例2:最大不相交区间数量
    • 例3:区间分组
    • 例4:区间覆盖
  • 2 Huffman树
    • 例:合并果子
  • 3 排序不等式
    • 例:排队打水
  • 4 绝对值不等式
    • 例:货仓选址
  • 5 推公式
    • 例:耍杂技的牛


1 区间问题

排序 + 维护端点

例1:区间选点

AcWing 905. 区间选点

在这里插入图片描述

核心思路:维护右端点,判断区间不相交——某区间的左端点大于当前维护区间的右端点

  1. 将每个区间按右端点从小到大排序
  2. 从前往后依次枚举每个区间
    • 若所枚举区间已包含当前区间的点,则直接pass
    • 否则选择当前区间的右端点

理由:若当前区间存在点包含于所枚举区间,则其中必有其右端点,越靠右越有可能被更多的区间包含。

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;

int n;
PII range[N];	// (l, r)

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, [](PII &a, PII &b) {
		return a.second < b.second;
	});
	
	int res = 0, ed = -2e9;
	for (int i = 0; i < n; i++)
		if (range[i].first > ed) {	// 若不相交(左>当前右)
			res++;	// 选取当前右端点
			ed = range[i].second;	// 结束维护,转移至所枚举区间
		}
	printf("%d\n", res);
	
	return 0;
}

例2:最大不相交区间数量

AcWing 908. 最大不相交区间数量

在这里插入图片描述

(核心思路与实际所求的局部最值和上一题完全相同)

  1. 将每个区间按右端点从小到大排序
  2. 从前往后依次枚举每个区间
    • 若所枚举区间已包含当前区间的点,则直接pass
    • 否则选择当前区间的右端点

理由:若当前区间的右端点不包含于所枚举区间,则该两区间必定不相交,故可选择当前区间(实为从当前区间及与其重合的任意区间中任选一)。

/* 同上一例 */
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;

int n;
PII range[N];	// (l, r)

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, [](PII &a, PII &b) {
		return a.second < b.second;
	});
	
	int res = 0, ed = -2e9;
	for (int i = 0; i < n; i++)
		if (range[i].first > ed) {	// 若不相交(左>当前右)
			res++;	// 选取当前区间
			ed = range[i].second;	// 结束维护,转移至所枚举区间
		}
	printf("%d\n", res);
	
	return 0;
}

例3:区间分组

AcWing 906. 区间分组

在这里插入图片描述

核心思路:同时维护多个右端点,更新其最值

  1. 将每个区间按左端点从小到大排序
  2. 从前往后处理每个区间:判断能否将其放到某个现有的组中,即其是否与组内最右区间无交集
    • 若不存在这样的组,则开新组放此区间
    • 若存在这样的组,则将其放入并更新

可用小根堆快速筛出目前最右区间的右端点最小的组,若满足要求则删除堆顶并将当前区间右端点插入,最终堆中元素个数即为组数。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;

int n;
PII range[N];	// (l, r)

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 &r = range[i];
		if (heap.empty() || heap.top() >= r.first) heap.push(r.second);	// 不满足要求则直接插入
		else {	// 满足要求则删除堆顶后再插入
			heap.pop();
			heap.push(r.second);
		}
	}
	
	printf("%d\n", heap.size());
	
	return 0;
}

例4:区间覆盖

AcWing 907. 区间覆盖

在这里插入图片描述

核心思路:覆盖起点,更新起点

  1. 将每个区间按左端点从小到大排序
  2. 从前往后依次枚举每个区间,在所有能覆盖 s s s 的区间中,选右端点最大的区间(覆盖最多);然后将 s s s 更新成右端点的最大值
    • 若不存在能覆盖 s s s 的区间,则一定会出现空隙,必无解

理由:选择区间数最少 = 起点 s s s 被赶至终点 t t t 所需次数最少

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;

int n;
PII range[N];
int S, T;

int main() {
	scanf("%d%d%d", &S, &T, &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;) {
		int j = i, max_r = -2e9;
		while (j < n && range[j].first <= S) {	// 找左端点不超过S的区间的最远右端点
			max_r = max(max_r, range[j].second);
			j++;
		}
		
		if (max_r < S) break;	// 最短右端点小于S则说明无法覆盖,必无解
		
		res++;
		S = max_r;
		if (S >= T) {
			success = true;
			break;
		}
		
		i = j;
	}
	
	if (!success) res = -1;
	printf("%d\n", res);
	
	return 0;
}

2 Huffman树

带权路径最短

例:合并果子

AcWing 148. 合并果子

在这里插入图片描述

核心思想:每次挑出值最小的合并——建立哈夫曼树

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

int n;
priority_queue<int, vector<int>, greater<int> > heap;

int main() {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		int x;
		scanf("%d", &x);
		heap.push(x);
	}
	
	int res = 0;
	while (heap.size() > 1) {
		int x1 = heap.top();
		heap.pop();
		int x2 = heap.top();
		heap.pop();
		
		res += x1 + x2;
		heap.push(x1 + x2);
	}
	
	printf("%d\n", res);
	
	return 0;
}

3 排序不等式

排序

例:排队打水

AcWing 913. 排队打水

在这里插入图片描述

核心思想:将所有数从小到大排序,等待时间之和最小,为 ∑ i = 1 n t i × ( n − i ) \sum_{i=1}^n t_i×(n-i) i=1nti×(ni)

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 1e5 + 10;

int n;
int t[N];

int main() {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) scanf("%d", &t[i]);
	
	sort(t, t + n);
	
	long long res = 0;
	for (int i = 0; i < n; i++) res += (long long)t[i] * (n - 1 - i);
	printf("%lld\n", res);
	
	return 0;
}

4 绝对值不等式

三角不等式: ∣ ∣ a ∣ − ∣ b ∣ ∣ ≤ ∣ a ± b ∣ ≤ ∣ a ∣ + ∣ b ∣ ||a|-|b||≤|a±b|≤|a|+|b| ∣∣ab∣∣a±ba+b

常见题型:求 f ( x ) = ∣ x 1 − x ∣ + ∣ x 2 − x ∣ + ⋯ + ∣ x n − x ∣   ( x 1 ≤ x 2 ≤ ⋯ ≤ x n ) f(x)=|x_1-x|+|x_2-x|+\cdots+|x_n-x|\ (x_1≤x_2≤\cdots≤x_n) f(x)=x1x+x2x++xnx (x1x2xn) 的最值。

例:货仓选址

AcWing 104. 货仓选址

在这里插入图片描述

由绝对值三角不等式得 ∣ a − x ∣ + ∣ b − x ∣ ≥ ∣ a − b ∣ |a-x|+|b-x|≥|a-b| ax+bxab ,当且仅当 x ∈ [ a ,   b ] x\in[a,\ b] x[a, b] 时取得等号。要求 f ( x ) f(x) f(x) 的最小值,对其两两分组后放缩得 f ( x ) = ( ∣ x 1 − x ∣ + ∣ x n − x ∣ ) + ( ∣ x 2 − x ∣ + ∣ x n − 1 − x ∣ ) + ⋯ ≥ ( x n − x 1 ) + ( x n − 1 − x 2 ) + ⋯ \begin{align*} f(x) &=(|x_1-x|+|x_n-x|)+(|x_2-x|+|x_{n-1}-x|)+\cdots \\ &≥(x_n-x_1)+(x_{n-1}-x_2)+\cdots \end{align*} f(x)=(x1x+xnx)+(x2x+xn1x)+(xnx1)+(xn1x2)+ 逐项逼近最终可得: f ( x ) f(x) f(x) 取得最小值时, x x x有序数列 x 1 , x 2 , ⋯   , x n x_1,x_2,\cdots,x_n x1,x2,,xn中点——当 n n n 为奇数时, x = x n + 1 2 x=x_{\frac{n+1}2} x=x2n+1(即为中位数);当 n n n 为偶数时, x = x n 2 x=x_\frac{n}2 x=x2n x = x n 2 + 1 x=x_{\frac n2+1} x=x2n+1

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 1e5 + 10;

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 res = 0;
	for (int i = 0; i < n; i++) res += abs(a[i] - a[n / 2]);
	
	printf("%d\n", res);
	
	return 0;
}

5 推公式

例:耍杂技的牛

AcWing 125. 耍杂技的牛

在这里插入图片描述

思路:越重、越强壮的越应放下面,故按 w i + s i w_i+s_i wi+si 从小到大排序,表示从上到下堆叠。

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

typedef pair<int, int> PII;

const int N = 5e4 + 10;

int n;
PII cow[N];		// (w_i, s_i)

int main() {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) scanf("%d%d", &cow[i].first, &cow[i].second);
	
	sort(cow, cow + n, [](PII &a, PII &b) {
		return a.first + a.second < b.first + b.second;
	});
	
	int res = -2e9, sum = 0;
	for (int i = 0; i < n; i++) {
		res = max(res, sum - cow[i].second);
		sum += cow[i].first;
	}
	
	printf("%d\n", res);
	
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/583039.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023最新!Git2.40.0于win10环境下的安装

2023最新&#xff01;Git2.40.0于win10环境下的安装 git官网地址&#xff1a;https://git-scm.com/download/win/ 导航 文章目录 2023最新&#xff01;Git2.40.0于win10环境下的安装导航一、下载Git二、安装Git三、检验 一、下载Git Git官网选择自己所需的版本下载 二、安装…

恒驰喜报 | 12强精英对决,恒驰勇夺华为云数字化转型演讲赛亚军

4月28日落幕的“2024年上海销售伙伴赛马专项行动——华为云数字化转型演讲比赛”上&#xff0c;恒驰信息华为云解决方案首席架构师&#xff0c;在上海12家华为云核心伙伴的同台竞技中&#xff0c;凭借对数字化转型及华为云服务的深刻理解&#xff0c;夺得演讲比赛“第二名”的好…

单纯形投影算法

目录 一&#xff0c;任意点到平移坐标轴面的投影 1&#xff0c;求解目标 2&#xff0c;转换变量 3&#xff0c;求解结果 4&#xff0c;f(t)的导数 5&#xff0c;f(t)的最小值 二&#xff0c;任意点到标准单纯形的投影 1&#xff0c;求解目标 2&#xff0c;公式变形 3…

MATLAB数值类型

MATLAB 数值 MATLAB支持各种数字类&#xff0c;包括有符号和无符号整数以及单精度和双精度浮点数。默认情况下&#xff0c;MATLAB将所有数值存储为双精度浮点数。 您可以选择将任何数字或数字数组存储为整数或单精度数字。 所有数值类型都支持基本数组运算和数学运算。 转换…

好看的PPT目录怎么做?推荐2款一键生成目录的AI PPT软件!

一份完整的 PPT 演示文稿&#xff0c;由多个页面组成&#xff0c;包括 PPT 封面页、PPT 目录页、PPT 分隔页&#xff08;PPT 过渡页&#xff09;、PPT 内容页、PPT 结束页&#xff0c;每一个页面类型&#xff0c;在整个 PPT 中起到不同的作用&#xff1a; PPT 封面页是 PPT 的…

蒸镀的氧化硅薄膜为什么有时候是绿色有时候是棕色的?

知识星球&#xff08;星球名&#xff1a;芯片制造与封测社区&#xff0c;星球号&#xff1a;63559049&#xff09;里的学员问&#xff1a;我们用热阻式蒸镀设备镀氧化硅薄膜&#xff0c;出来的颜色有时候会发生变化是什么原因呀&#xff1f;有时候薄膜是绿色有时候是棕色。 氧…

金蝶云星空与旺店通·企业版对接集成付款申请单查询连通创建调拨入库单

金蝶云星空与旺店通企业版对接集成付款申请单查询连通创建调拨入库单 数据源平台:金蝶云星空 金蝶K/3Cloud&#xff08;金蝶云星空&#xff09;是移动互联网时代的新型ERP&#xff0c;是基于WEB2.0与云技术的新时代企业管理服务平台。金蝶K/3Cloud围绕着“生态、人人、体验”&a…

智能物联网与Web3:连接未来数字生活的桥梁

随着科技的不断进步&#xff0c;智能物联网&#xff08;IoT&#xff09;和Web3技术正成为数字化时代的关键驱动力。智能物联网将各种物理设备连接到互联网&#xff0c;使其能够感知环境、收集数据并与其他设备通信&#xff0c;而Web3技术则以去中心化、安全性和透明性为核心&am…

DataX数据采集流程(项目)

目录 1.CDH介绍 2.ClouderaManager架构 3.服务器 4.dataX架构 5.Datax数据处理流程 6.DataX的使用说明 7.Mysql数据切割 8.Mysql数据导入HDFS 9.查询站点 站点页面如下&#xff0c;可进一步查询导入的数据内容 10.dataX-Web访问页面 创建数据库连接 1.CDH介绍 --(…

NDK 入门(二)—— 调音小项目

NDK 入门系列主要介绍 JNI 的相关内容&#xff0c;目录如下&#xff1a; NDK 入门&#xff08;一&#xff09;—— JNI 初探 NDK 入门&#xff08;二&#xff09;—— 调音小项目 NDK 入门&#xff08;三&#xff09;—— JNI 注册与 JNI 线程 NDK 入门&#xff08;四&#xff…

【错题集-编程题】重排字符串(贪心 + 构造)

牛客对应题目链接&#xff1a;重排字符串 (nowcoder.com) 力扣对应题目链接&#xff1a;1054. 距离相等的条形码 - 力扣&#xff08;LeetCode&#xff09; 一、分析题目 二、代码 1、没看题解之前AC的代码 //牛客代码(看了题解之后AC的代码) #include <iostream> #inc…

【Python BUG】connect: permission denied.

问题描述 解决方案 本质是权限问题 sudo密码即可

C语言阶段性测试错题纠正与拓展

引言&#xff1a;在2024年4月26日&#xff0c;我进行了C语言知识的“期末考试”。通过这次考试&#xff0c;我发现了我的知识漏洞。所以&#xff0c;我写下这篇博客来记录我的错题&#xff0c;并进行纠正&#xff0c;然后对于以前遗忘知识的回顾。 更多有关C语言的知识详解可前…

什么是摇摆交易?澳福一篇文章全面解读

摇摆交易是八大外汇交易策略其中一种交易策略。摇摆交易基于这样的想法&#xff0c;交易者希望利用波动范围和趋势市场的优势&#xff0c;通过选择“顶部”和“底部”&#xff0c;交易者可以相应地输入多头和空头头寸。即可以应用局部校正来最大化利润。fpmarkets澳福认为这种交…

P5931 灯泡

题目描述 相比 Wildleopard 的家&#xff0c;他的弟弟 Mildleopard 比较穷。他的房子是狭窄的&#xff0c;而且在他的房间里仅有一个灯泡。每天晚上&#xff0c;他徘徊在自己狭小的房子里&#xff0c;思考如何赚更多的钱。有一天&#xff0c;他发现他的影子的长度随着他在灯泡…

【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码

文章目录 一、游戏运行效果二、代码实现2.1 项目搭建2.2 加载我方坦克2.3 加载敌方坦克2.4 添加爆炸效果2.5 坦克大战之音效处理 三、完整代码 一、游戏运行效果 二、代码实现 坦克大战游戏 2.1 项目搭建 本游戏主要分为两个对象&#xff0c;分别是我方坦克和敌方坦克。用户可…

人工智能技术在教育中的潜力有多大

原文&#xff1a;人工智能技术在教育中的潜力有多大&#xff1f; - 知乎 作者&#xff1a;大全Prompt 链接&#xff1a;https://www.zhihu.com/question/637034129/answer/3346272227 来源&#xff1a;知乎 谢邀&#xff1a;在技术快速发展的今天&#xff0c;人工智能&#x…

数据复制的艺术:深拷贝与浅拷贝在JavaScript中的实现方式

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热爱技术和分享&#xff0c;欢迎大家交流&#xff0c;一起学习进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 目录 赋值和拷贝 浅拷贝与深拷贝区别 浅拷贝的实现方式 1.Object.assign() 2.…

变革 Perplexica:AI驱动的问答搜索引擎

Perplexica是一个开源的人工智能搜索工具&#xff0c;也可以说是一款人工智能搜索引擎&#xff0c;它深入互联网以找到答案。受Perplexity AI启发&#xff0c;它是一个开源选择&#xff0c;不仅可以搜索网络&#xff0c;还能理解您的问题。它使用先进的机器学习算法&#xff0c…

国产Sora诞生!清华团队发布Vidu大模型,可直接生成16秒视频

大模型之争已从单模态转向多模态。 4月27日&#xff0c;在2024中关村论坛年会未来人工智能先锋论坛上&#xff0c;清华大学联合北京生数科技有限公司正式发布了文生视频大模型——Vidu。 在会议上&#xff0c;清华大学人工智能研究院副院长、生数科技首席科学家朱军对外展示了…
最新文章