NO.64十六届蓝桥杯备战|基础算法-简单贪心|货仓选址|最大子段和|纪念品分组|排座椅|矩阵消除(C++)

贪⼼算法是两极分化很严重的算法。简单的问题会让你觉得理所应当,难⼀点的问题会让你怀疑⼈⽣

什么是贪⼼算法?

贪⼼算法,或者说是贪⼼策略:企图⽤局部最优找出全局最优。

  1. 把解决问题的过程分成若⼲步;
  2. 解决每⼀步时,都选择"当前看起来最优的"解法;
  3. "希望"得到全局的最优解。
贪⼼算法的特点
  1. 对于⼤多数题⽬,贪⼼策略的提出并不是很难,难的是证明它是正确的。因为贪⼼算法相较于暴⼒枚举,每⼀步并不是把所有情况都考虑进去,⽽是只考虑当前看起来最优的情况。但是,局部最优并不等于全局最优,所以我们必须要能严谨的证明我们的贪⼼策略是正确的。
    ⼀般证明策略有:反证法,数学归纳法,交换论证法等等。
  2. 当问题的场景不同时,贪⼼的策略也会不同。因此,贪⼼策略的提出是没有固定的套路和模板的。我们后⾯讲的题⽬虽然分类,但是⼤家会发现具体的策略还是相差很⼤。因此,不要妄想做⼏道贪⼼题⽬就能遇到⼀个会⼀个。有可能做完50道贪⼼题⽬之后,第51道还是没有任何思路。
如何学习贪⼼?

先有⼀个认知:做了⼏⼗道贪⼼的题⽬,遇到⼀个新的⼜没有思路,这时很正常的现象,把⼼态放平。

  1. 前期学习的时候,重点放在各种各样的策略上,把各种策略当成经验来吸收;
  2. 在平常学习的时候,我们尽可能的证明⼀下这个贪⼼策略是否正确,这样有利于培养我们严谨的思维。但是在⽐赛中,能想出来⼀个策略就已经不错了,如果再花费⼤量的时间去证明,有点得不偿失。这个时候,如果根据贪⼼策略想出来的若⼲个边界情况都能过的话,就可以尝试去写代码了。
P10452 货仓选址 - 洛谷

将所有的商店按照「从⼩到⼤」的顺序「排序」,把货仓建在中位数处,可以使得货仓到每家商店的距离之和最⼩:

  • 如果n是奇数,货仓建在a[(n + 1)/2] 位置处;
  • 如果n是偶数,货仓建在a[n/2] ∼ a[n/2 + 1]之间都是可以的
#include <bits/stdc++.h>
using namespace std;typedef long long LL;const int N = 1e5+10;int n;
int a[N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n;for (int i = 1; i <= n; i++) cin >> a[i];sort(a+1, a+1+n);LL ret = 0;for (int i = 1; i <= n; i++){//中间位置的下标是(1+n)/2ret += abs(a[i] - a[(1+n) / 2]);}cout << ret << endl;return 0;
}

∣ a − x ∣ + ∣ b − x ∣ ≥ ∣ a − b ∣ |a-x|+|b-x| \ge |a-b| ax+bxab
![[Pasted image 20250404104208.png]]

当x处于两者的中间位置时,左式取得最小值
形如:
s u m = ∑ i = 1 n ∣ a [ i ] − x ∣ = ∣ a [ 1 ] − x ∣ + ∣ a [ 2 ] − x ∣ + ⋯ + ∣ a [ n ] − x ∣ sum = \sum^{n}_{i=1}|a[i]-x|=|a[1]-x|+|a[2]-x|+\dots+|a[n]-x| sum=i=1na[i]x=a[1]x+a[2]x++a[n]x

  • 当x 取到n 个数的中位数时,和最⼩;
  • 最⼩和为:
    ( a [ n ] − a [ 1 ] ) + ( a [ n − 1 ] − a [ 2 ] ) + . . . + ( a [ n + 1 − n / 2 ] − a [ n / 2 ] ) (a[n] - a[1]) + (a[n - 1] - a[2]) + ... + (a[n + 1 - n/2] - a[n/2]) (a[n]a[1])+(a[n1]a[2])+...+(a[n+1n/2]a[n/2])
#include <bits/stdc++.h>
using namespace std;typedef long long LL;const int N = 1e5+10;int n;
int a[N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n;for (int i = 1; i <= n; i++) cin >> a[i];sort(a+1, a+1+n);LL ret = 0;for (int i = 1; i <= n/2; i++){ret += abs(a[i] - a[n+1-i]);      }cout << ret << endl;return 0;
}
P1115 最大子段和 - 洛谷

贪⼼想法:从前往后累加,我们会遇到下⾯两种情况:

  • ⽬前的累加和>=0:那么当前累加和还会对后续的累加和做出贡献,那我们就继续向后累加,然后更新结果;
  • ⽬前的累加和<0:对后续的累加和做不了⼀点贡献,直接⼤胆舍弃计算过的这⼀段,把累加和重置为0,然后继续向后累加。
    这样我们在扫描整个数组⼀遍之后,就能更新出最⼤⼦段和。
    ![[Pasted image 20250404143727.png]]

在累加的过程中算出⼀段区间和sum[a,b]<0 ,如果不舍弃这⼀段,那么[a,b]段之间就会存在⼀点,「以某个位置为起点」就会「更优」,分为下⾯两种情况

  1. 在ab段存在⼀个点c ,从这个位置开始,「越过b 」的累加和⽐从a 开始的累加和更优:
    ⽤「反证法」证明这种情况不存在。
    如果存在这⼀点,那么:sum[c, b] > sum[a, b] ,这样才能保证向后加的时候更优。
    但这是「不可能」的。如果sum[c, b] > sum[a, b] ,那么sum[a, c-1]<0,这与我们的贪⼼策略⽭盾。
    因为我们贪⼼策略向后加的时候,只要不⼩于0,就会⼀直加下去。如果[a, c-1]段⼩于0,就
    会在c点之前停⽌,不会累加到b。
    因此区间内不存在⼀点,在计算⼦数组和时,在「越过b 」的情况下,能⽐从a 开始更优。
  2. 在ab段存在⼀个点c ,从这个位置开始,「不越过b 」的累加和⽐从a 开始的累加和更优:
    也可以⽤「反证法」证明这种情况不存在。
    如果存在这⼀点,那么:sum[c, k] > sum[a, k]
    但这是不可能的。如果sum[c, k] > sum[a, k],那么sum[a, c - 1] < 0 ,这与我们的贪⼼策略⽭盾。
    因此区间内不存在⼀点,在计算⼦数组和时,在「不越过b 」的情况下,能⽐从a 开始更优。
    综上所述,我们可以⼤胆舍弃这⼀段,重新开始。
#include <bits/stdc++.h>
using namespace std;const int N = 2e5 + 10;typedef long long LL;int n;
LL a[N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n;for (int i = 1; i <= n; i++) cin >> a[i];LL sum = 0, ret = -1e6;for (int i = 1; i <= n; i++){sum += a[i];ret = max(ret, sum);if (sum < 0) sum = 0;}cout << ret << endl;return 0;
}
P1094 [NOIP 2007 普及组] 纪念品分组 - 洛谷

先将所有的纪念品排序,每次拿出当前的最⼩值x 与最⼤值y :

  • 如果x + y ≤ w :就把这两个放在⼀起;
  • 如果x + y > w:说明此时最⼤的和谁都凑不到⼀起,y单独分组,x继续留下在进⾏下⼀次判断。
    直到所有的物品都按照上述规则分配之后,得到的组数就是最优解

可以⽤「交换论证法」证明贪⼼解就是最优解:
对于区间[ai......aj],如果存在最优解,但是aiaj的分配⽅式与我们贪⼼解的分配⽅式不⼀样,那么就会有以下⼏种情况:

  1. a[i] + a[j] > w时:
  • 贪⼼解会把a[j]单独分组,a[i]留待下次考虑;
  • 最优解也必定会把a[j]单独分组,因为没有更⼩的值与a[j]组合。
    此时贪⼼解与最优解⼀致。
  1. a[i] + a[j] ≤ w时:
  • 贪⼼解会把两者组合分在⼀个组⾥⾯;
  • 最优解可能有以下⼏种情况:
    • a[j]单独⼀组:
      • 如果a[i]也单独⼀组的话,最优解还不如贪⼼解分的组少,⽭盾;
      • 如果a[i]和另⼀个a[k]⼀组的话,我们可以把a[k]a[j]交换,此时并不影响结果,和贪⼼解⼀致。
    • a[j]a[k]⼀组:
      • 如果a[i]单独⼀组的话,交换a[i]a[k],此时并不影响最终结果,和贪⼼解⼀致;
      • 如果a[i]a[l]⼀组的话,交换a[i]a[k],此时变成(a[i]+a[j]),(a[l]+a[k]),其中a[l]+a[k]<=a[j]+a[k]<=w,不影响最终结果,和贪⼼解⼀致。
        综上所述,我们可以通过不断的「调整」,使的最优解在「不改变其最优性」的前提下,变得和贪⼼解⼀致。那我们的贪⼼策略就等价于最优策略。
#include <bits/stdc++.h>
using namespace std;const int N = 3e4 + 10;int w, n;
int a[N];int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> w >> n;for (int i = 1; i <= n; i++) cin >> a[i];sort(a+1, a+1+n);int l = 1, r = n, ret = 0;while (l <= r){if(a[l] + a[r] <= w) l++, r--;else r--;ret++;}cout << ret << endl;return 0;
}
P1056 [NOIP 2008 普及组] 排座椅 - 洛谷

由题意可得,我们会发现⼀些性质:

  • 设置横向通道的时候,并「不影响」左右相邻的同学;
  • 设置纵向通道的时候,并「不影响」上下相邻的同学。
    因此我们可以「分开」处理横向通道和纵向通道。
    处理横向通道(纵向同理,就不多赘述):
  • 收集每⼀⾏如果放上通道之后,会解决多少个交头接⽿的同学;
  • 对收集的信息「从⼤到⼩」排序,选最⼤的k ⾏就是最优结果。
#include <bits/stdc++.h>
using namespace std;const int N = 1010;struct node
{int index;int cnt;
}row[N], col[N];int m, n, k, l, d;//按cnt从大到小
bool cmp1(node& x, node& y)
{return x.cnt > y.cnt;
}
//按index从小到大
bool cmp2(node& x, node& y)
{return x.index < y.index;
}int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> m >> n >> k >> l >> d;//初始化结构体数组for (int i = 1; i <= m; i++) row[i].index = i;for (int i = 1; i <= n; i++) col[i].index = i;while(d--){int x, y, p, q; cin >> x >> y >> p >> q;if (x == p) col[min(y, q)].cnt++;else row[min(x, p)].cnt++;}//对两个数组按照cnt从大到小排序sort(row+1, row+1+m, cmp1);sort(col+1, col+1+n, cmp1);//对row数组,前k个元素,按照下标从小到大排序sort(row+1, row+1+k, cmp2);//对col数组,前l个元素,按照下标从小到大排序sort(col+1, col+1+l, cmp2);for (int i = 1; i <= k; i++){cout << row[i].index << " ";}cout << endl;for (int i = 1; i <= l; i++){cout << col[i].index << " ";}cout << endl;return 0;
}
矩阵消除游戏

最优解是先暴⼒枚举所有⾏的选法,在⾏的选择都确定之后,再去贪⼼的处理列

#include <bits/stdc++.h>
using namespace std;const int N = 20;int n, m, k;
int a[N][N];
int col[N]; //统计列和//统计x的二进制中1的个数
int calc(int x)
{int ret = 0;while (x){ret++;x -= x & -x;}return ret;
}//从大到小排序
bool cmp(int a, int b)
{return a > b;
}int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n >> m >> k;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)cin >> a[i][j];int ret = 0;//暴力枚举行所有选法for (int st = 0; st < (1 << n); st++){int cnt = calc(st);if (cnt > k) continue; //不合法memset(col, 0, sizeof col);int sum = 0; //记录当前选法的和for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){if ((st >> i) & 1) sum += a[i][j];else col[j] += a[i][j];}}//处理列sort(col, col + m, cmp);//选k - cnt列for (int j = 0; j < min(k - cnt, m); j++) sum += col[j];ret = max(ret, sum);}cout << ret << endl;return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux(十二)信号

今天我们就要来一起学习信号啦&#xff01;&#xff01;&#xff01;还记得小编在之前的文章中说过的ctrlc吗&#xff1f;之前小编没有详细介绍过&#xff0c;现在我们就要来学习啦&#xff01;&#xff01;&#xff01; 一、信号的基本介绍 首先&#xff0c;小编带领大家先一…

Dify开发实战-自制插件 和安装python3最新版本 记录版本 后续会持续更新

自定义插件 Dify 插件脚手架工具Python 环境&#xff0c;版本号 ≥ 3.12 安装Python 一 进入官网 https://www.python.org/downloads/windows/ 点击下载 二、安装python&#xff08;本文中有借鉴其他图片 所以图片展示python版本可能不一致 请忽略&#xff09; 1.双击打开py…

Docker安装、配置Redis

1.如果没有docker-compose.yml文件的话&#xff0c;先创建docker-compose.yml 配置文件一般长这个样子 version: 3services:redis:image: redis:latestcontainer_name: redisports:- "6379:6379"command: redis-server --requirepass "123456"restart: a…

Parasoft C++Test软件单元测试_操作指南

系列文章目录 Parasoft C++Test软件静态分析:操作指南(编码规范、质量度量)、常见问题及处理 Parasoft C++Test软件单元测试:操作指南、实例讲解、常见问题及处理 Parasoft C++Test软件集成测试:操作指南、实例讲解、常见问题及处理 进阶扩展:自动生成静态分析文档、自动…

二级索引详解

二级索引详解 二级索引(Secondary Index)是数据库系统中除主键索引外的附加索引结构,用于加速基于非主键列的查询操作。以下是关于二级索引的全面解析: 一、核心概念 特性主键索引 (Primary Index)二级索引 (Secondary Index)唯一性必须唯一可以唯一或非唯一数量每表只有…

Python_level1_字符串_11

目录 一、基本概念 二、字符串基本操作&#xff1a;【索引、切片、遍历】 1.字符串与列表&#xff08;相同&#xff09; 1&#xff09;索引&#xff08;从0开始&#xff09;(可以获取某一个/某几个连续的字符) 2&#xff09;切片 [xx:xx] 与 列表 语法规则一样 [起…

Axure数据可视化科技感大屏设计资料——赋能多领域,展示无限价值

可视化大屏如何高效、直观地展示数据&#xff0c;并将其转化为有价值的决策依据&#xff0c;成为了许多企业和组织面临的共同挑战。Axure大屏可视化模板&#xff0c;作为一款强大的数据展示工具&#xff0c;正在以其出色的交互性和可定制性&#xff0c;赋能多个领域&#xff0c…

MySQL 性能调优:数据库的极限运动训练

就像运动员需要不断训练才能突破极限&#xff0c;数据库也需要各种调优才能跑得更快…让我们一起给 MySQL 安排一套专业的"健身计划"&#xff01; 什么是 MySQL 性能调优&#xff1f;&#x1f914; MySQL 性能调优是指通过各种配置优化、结构调整和查询改进&#x…

4.5/Q1,GBD数据库最新文章解读

文章题目&#xff1a;Emerging trends and cross-country health inequalities in congenital birth defects: insights from the GBD 2021 study DOI&#xff1a;10.1186/s12939-025-02412-7 中文标题&#xff1a;先天性出生缺陷的新趋势和跨国健康不平等&#xff1a;GBD 202…

基于DeepSeek、ChatGPT支持下的地质灾害风险评估、易发性分析、信息化建库及灾后重建

前言&#xff1a; 地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。在降水、地震等自然诱因的作用下&#xff0c;地质灾害在全球范围内频繁发生。我国不仅常见滑坡灾害&#xff0c;还…

Linux | 安装超级终端串口软件连接i.MX6ULL开发板(8)

01 它的安装步骤也非常简单,安装语言选择中文简体,点击确定,如下图所示。 点击下一步,如下图所示。 02

蓝桥杯15届 宝石组合

问题描述 在一个神秘的森林里&#xff0c;住着一个小精灵名叫小蓝。有一天&#xff0c;他偶然发现了一个隐藏在树洞里的宝藏&#xff0c;里面装满了闪烁着美丽光芒的宝石。这些宝石都有着不同的颜色和形状&#xff0c;但最引人注目的是它们各自独特的 “闪亮度” 属性。每颗宝…

Lua:第1-4部分 语言基础

1 Lua语言入门 1.1 程序段 我们将 Lua 语言执行的每一段代码&#xff08;例如&#xff0c;一个文件或交互模式下的一行&#xff09;称为一个程序段 &#xff08; Chunk &#xff09; &#xff0c;即一组命令或表达式组成的序列 。 1.2 一些词法规范 Lua 语言中的标识符&#…

CTF类题目复现总结-hashcat 1

一、题目地址 https://buuoj.cn/challenges#hashcat二、复现步骤 1、下载附件&#xff0c;解压得到What kind of document is this_文件&#xff1b; 2、用010 Editor打开What kind of document is this_文件&#xff0c;发现是office文件&#xff1b; 3、将后缀名改为ppt时…

手机归属地查询Api接口,数据准确可靠

手机归属地查询是一项非常实用的功能&#xff0c;它可以帮助我们快速了解一个手机号码的所属地区、区号、邮政编码等信息。在互联网时代&#xff0c;随着大数据和人工智能技术的发展&#xff0c;手机归属地查询的API接口也变得越来越普及和便捷。 在本文中&#xff0c;我们将介…

orangepi zero烧录及SSH联网

下载对应版本的armbian镜像 armbian的默认用户root&#xff0c;默认密码&#xff1a;1234 下载烧录工具win32diskimager https://sourceforge.net/projects/win32diskimager/files/Archive/ 插入16G以上TF卡&#xff0c;使用win32diskimager烧录armbian镜像 烧录完毕后用l…

为什么有的深度学习训练,有训练集、验证集、测试集3个划分,有的只是划分训练集和测试集?

在机器学习和深度学习中&#xff0c;数据集的划分方式取决于任务需求、数据量以及模型开发流程的严谨性。 1. 三者划分&#xff1a;训练集、验证集、测试集 目的 训练集&#xff08;Training Set&#xff09;&#xff1a;用于模型参数的直接训练。验证集&#xff08;Validati…

Linux驱动开发 块设备

目录 序言 1.块设备结构 分区(gendisk) 请求(request) 请求队列 1. 多队列架构 2. 默认限制与扩展 bio 2.块设备的使用 头文件与宏定义 blk-mq 相关结构和操作 块设备操作函数 模块初始化函数 模块退出函数 3.总结 序言 块设备&#xff08;如硬盘、虚拟盘&#x…

ResNet改进(14):添加 EMA注意力机制提升跨空间学习效率

本专栏代码均经过测试,可以直接替换项目中的模型,一键运行! 采用最新的即插即用模块,有效涨点!! 1.EMA注意力机制 EMA(Efficient Multi-scale Attention)注意力机制是一种创新的注意力设计,能够有效提升模型在跨空间学习任务中的表现。以下是对该机制的详细解析: EM…

计算机硬件——CPU 主要参数

什么是 CPU &#xff1f; CPU 的英文全称是 Central Processing Unit&#xff0c;即中央处理器。CPU 的内部结构可分为控制单元、逻辑单元和存储单元三大部分。CPU 的性能大致上反映出了它所配置的微机的性能&#xff0c;因此 CPU 的性能指标十分重要。 CPU 的主要参数 CPU …