贪心算法笔记

embedded/2025/1/14 23:45:42/

贪心算法笔记

大概内容

贪心就是对于一个问题有很多个步骤,我们在每一个步骤中都选取最优的那一个,最后得出答案。就是在一些函数中可行,但是有些比如二次函数,因为它的转折点不一定最优,就是不可行的。那么如何判断贪心呢?有这么几种

  • 看时间复杂度,一般的就是 O ( n ) O(n) O(n) 或者是排序 O ( n   l o g n ) O(n \ log n) O(n logn)
  • 或者猜测,看着像就可以试试。
  • 自己用数学证明方法,比如归纳法,交换法,就是如果交换之后答案变得小或者大就可以了。

那贪心在比赛中怎么办呢?可以先尝试一下大小样例,再尝试对拍,有个保底,如果可以也可以证明一下。

然后还有一种贪心,叫做反悔贪心,就是可以撤销,也没别的。

最后因为贪心每次取局部最优,所以代码不长,而且时间复杂度不大。

例题讲解
凌乱的yyy / 线段覆盖

题目大意:有 n n n 个线段,问最多有多少个不重叠的线段。

思路:贪心,然后按照 r i r_{i} ri 排序,每次选取尽可能早的场次并且要合法,也就是不能前面重叠。

证明:如果不相交,那么图片如下。

img

很明显,一场弄完,另一场。如果包含,图片如下:

img

那样我们就可以选择第一场,因为它结束得早,可以取另外的场次。所以证明取更早的是永远比更晚的要更优。

时间复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn)

#include<bits/stdc++.h>
struct noip//有同学不会结构体的多开几个数组 
{int begin;//开始时间 int finish;//结束时间 
}a[2000005];
bool cmp(noip x,noip y)
{return x.finish<y.finish;//按结束时间排 
}
using namespace std;
int main()
{int n,ans=1;//初始化 cin>>n; for(int i=1;i<=n;i++){cin>>a[i].begin>>a[i].finish;}sort(a+1,a+n+1,cmp);//快速排序(不用我多说了吧) int mini=a[1].finish;//定义mini统计最后结束时间 int j=1;while(j<=n)//我用了while,感兴趣的同学可以用for(提示:for不用定义j) {j++;if(a[j].begin>=mini)//新的比赛开始时间要晚于mini {ans++;//统计比赛数 mini=a[j].finish;//更新mini }}cout<<ans<<endl;//输出 return 0;//功德圆满 
}
Teleporters (Easy Version)

思路:直接 a i + i a_{i}+i ai+i 排序,就好了。

证明:就是每次都是走过去,传回来,所以直接排序就可以了。

时间复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn)

#include<bits/stdc++.h>
using namespace std;
struct node
{int x,id;
}c[200005];
int n,m,tmp;
bool cmp(node a,node b)
{return a.x+a.id<=b.x+b.id;//跟思路一样排序
}
int main()
{int t;cin>>t;while(t--){memset(c,0,sizeof(c));cin>>n>>m;for(int i=1;i<=n;i++){cin>>tmp;c[i].x=tmp;c[i].id=i;}sort(c+1,c+n+1,cmp);int i=0;while(m>=0&&i<=n){i++;m=m-c[i].x-c[i].id;}cout<<i-1<<endl;	}return 0;
}
Teleporters (Hard Version)

思路:这一题就是先前缀和记录一下能用的传送门的价值之和,然后在使用二分答案,但是因为起点是 0 0 0 的缘故,所以还要另外枚举 0 0 0 点。

#include<bits/stdc++.h>
#define maxn 2900001
#define int long long
using namespace std;
int T,n,m,ans,a[maxn],s[maxn];
int check(int c,int x,int id)
{//二分最长的合法前缀区间int l=1,r=n,sum=-1;while(l<=r){int mid=l+r>>1;if(s[mid]-(mid>=id?x:0)<=c)sum=mid+(mid>=id?-1:0),l=mid+1;//特判x的影响else r=mid-1;}return sum==-1?0:sum;//可能无解
}
signed main()
{scanf("%lld",&T);while(T--){ans=0;map<int,int>mp;//记录位置scanf("%lld%lld",&n,&m);for(int i=1;i<=n;i++) {scanf("%lld",&a[i]);s[i]=min(a[i]+(n-i+1),a[i]+i);//取最小花费}sort(s+1,s+n+1);for(int i=1;i<=n;i++) mp[s[i]]=i,s[i]+=s[i-1];//前缀和for(int i=1;i<=n;i++){if(m-a[i]-i<0) continue;//可能不合法ans=max(ans,check(m-a[i]-i,min(a[i]+(n-i+1),a[i]+i),mp[min(a[i]+(n-i+1),a[i]+i)])+1);//注意要加上当前点i}printf("%lld\n",ans);}return 0;
}
国王游戏

思路:就是按照 a i b i a_ib_i aibi​​的大小从小到大排序

证明:我们不妨设两个人分别写了 a 1 , b 1 , a 2 , b 2 a_1,b_1,a_2,b_2 a1,b1,a2,b2 且满足 a 1 b 1 > a 2 b 2 a_1b_1>a_2b_2 a1b1>a2b2 则有 a 2 b 1 = a 1 b 2 \tfrac{a_2}{b_1}=\tfrac{a_1}{b_2} b1a2=b2a1

所以有一下两种情况

  1. 1在2的前面
  2. 1在2的后面

设在设在 1 , 2 1,2 1,2 之前所有人左手乘积为 k k k,那么对于第一种情况,我们的答案就是

a n s 1 = max ⁡ ( k b 1 , k a 1 b 2 )  


http://www.ppmy.cn/embedded/153963.html

相关文章

【STM32-学习笔记-5-】ADC

文章目录 ADCADC函数Ⅰ、ADC_InitTypeDef结构体参数①、ADC_Mode②、ADC_DataAlign③、ADC_ExternalTrigConv④、ADC_ContinuousConvMode⑤、ADC_ScanConvMode⑥、ADC_NbrOfChannel Ⅱ、ADC配置示例1、单次转换&#xff0c;非扫描单次转换非扫描模式下&#xff0c;获取多通道的…

《CPython Internals》阅读笔记:p118-p150

《CPython Internals》学习第 8 天&#xff0c;p118-p150 总结&#xff0c;总计 33 页。 一、技术总结 补充一些本人整理的关于 Context-Free Grammar(CFG) 的知识。 1.symbol(符号) A mathematical symbol is a figure or a combination of figures that is used to repre…

第六章:网页设计

文章目录&#xff1a; 一&#xff1a;网页设计 1.基本概念 1.1 网页 1.2 网站 1.3 工具 2.HTML语言 2.1 基础 2.2 标记 2.2.1 结构 2.2.2 文本 2.2.3 功能 2.2.4 表单 2.3 属性 二&#xff1a;IIS 1.定义 2.主要功能 3.特点与优势 4.应用场景 4.1 安装IIS …

Redis:数据类型

1. 字符串&#xff08;String&#xff09; 简介 概念&#xff1a;这是最简单的数据类型&#xff0c;可以存储字符串、整数或浮点数。特点&#xff1a;支持原子操作&#xff0c;如递增和递减数值。 示例 # 设置一个键值对 SET mykey "Hello, Redis!"# 获取该键的值…

如何添加合适的索引:MySql 数据库索引认知

写在前面 博文内容涉及 Mysql 数据库索引简单认知&#xff0c;包括SQL执行过程&#xff0c;数据库数据存储原理。如何通过索引加快数据查询原理简单介绍适合有一定SQL基础的开发运维小伙伴建立数据库索引认知&#xff0c;学会如何添加索引理解不足小伙伴帮忙指正 &#x1f603;…

CentOS 7.9 通过 yum 安装 Docker

文章目录 前言一、删除已安装的 Docker二、网络设置三、设置 yum 源&#xff0c;并安装依赖四、设置 Docker 仓库五、安装及使用 Docker六、镜像仓库总结 前言 CentOS 7.9 过了维护期&#xff0c;Docker 官方文档没有了相关的安装文档。记录一下&#xff0c;备用&#xff01; …

Django Admin 自定义操作封装

1. 为什么需要封装? 在Django开发中,我们经常需要在Admin界面添加自定义操作按钮,以便管理员执行特定的任务。通过封装,我们可以: 减少重复代码统一管理自定义操作的逻辑提高代码的可维护性和可扩展性 © ivwdcwso (ID: u012172506)2. CustomActionMixin 的实现 让我…

Java - Http 通讯

Java - Http 通讯 PS&#xff1a; 1. Http 协议 POST | GET 请求&#xff1b; 2. 支持 报头、报文、参数 自定义配置&#xff1b; 3. GET 返回支持 String | Stream; 4. 相关依赖&#xff1a; <dependency><groupId>org.apache.httpcomponents</groupId><…