P1824 [USACO05FEB] 进击的奶牛 Aggressive Cows G

【编译原理】LL(1)分析方法 生成语法树(c++实现) 基本流程 输入文法->消除左递归->提取左公共因子->求FIRST集->求FOLLOW集->LL(1)分析表->表驱动的预测语法分析过程->输出语法分析结果和语法树 阅读详情

记录145

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int main(){
	int n=0,m=0;
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+n+1); // 牛舍位置不一定有序,必须先排序,为后续贪心做准备
	
	int ans=0;
	int L=1,R=a[n],mid=0; // 二分答案:最小距离的下界是1,上界是最大坐标差
	while(L<=R){
		mid=(L+R)/2;
		// 贪心验证:假设当前两头牛的最小距离为 mid,最多能放几头牛?
		int cnt=1; // 计数器:第一头牛默认放在第一个牛舍 a[1]
		int t=a[1]; // 记录上一头牛放置的位置
		
		for(int i=2;i<=n;i++){
			// 如果当前牛舍与上一头牛的距离 >= mid,说明可以放下一头牛
			if(a[i]-t>=mid){
				cnt++;
				t=a[i]; // 更新上一头牛的位置为当前牛舍
			}
		}
		
		// 如果能放下的牛少于 m 头,说明 mid 太大了,需要减小距离
		if(cnt<m) R=mid-1;
		else{ // 如果能放下 m 头或更多,说明 mid 可行,尝试更大的距离
			ans=mid;
			L=mid+1;
		}
	}
	cout<<ans;
    return 0;
}

题目传送门https://www.luogu.com.cn/problem/P1824


前言

我是一名专注信奥赛(CSP-J/S、NOIP)的教练。

  • 如果你觉得这篇题解对你有帮助,欢迎点击关注我的优快云账号,我会持续更新高质量算法解析。
  • 我深知算法思维的构建远比单纯通过题目更重要,本系列题解不局限于AC代码的堆砌,而是致力于拆解题目背后的逻辑链条与核心知识点
  • 备赛路上若遇瓶颈,欢迎随时评论或私信,我将甄选典型疑难问题,通过视频讲解或撰写专项文章的形式,为你提供深度答疑。

 核心解题思路

这道题是一道非常经典的“最大值最小化”(或最小值最大化)问题,通常使用二分答案 + 贪心验证的策略来解决。

  1. 问题转化:
    题目要求“最大化最近的两头牛之间的距离”。直接去求这个最大值非常困难,因为组合情况太多。但如果我们反过来思考:假设我们知道了两头牛之间的最小距离是 dd ,我们能不能判断在这个距离下,能不能放下 mm 头牛?如果能放下,说明 dd 是可行的,我们可以尝试更大的距离;如果放不下,说明 dd 太大了,需要减小距离。

  2. 算法设计(二分答案 + 贪心):

    • 二分答案:因为牛舍坐标在 [0,10^9]之间,答案具有单调性(如果距离 d 可行,那么比 d 小的距离一定也可行)。因此,我们可以对“最小距离”进行二分查找。
    • 贪心验证(Check函数):在二分的过程中,我们需要一个验证函数。为了在限定的最小距离 midmid 下尽可能多地放下牛,我们采用贪心策略:将牛舍排序后,第一头牛永远放在第一个位置,后续的牛只要与上一头牛的距离大于等于 mid ,就立刻放下。这种策略能保证我们在不违反距离限制的前提下,最紧凑地放置牛,从而测试出当前 mid下最多能放多少头牛。

代码分块详细解释

1. 头文件、常量与数据预处理

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int main(){
	int n=0,m=0;
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+n+1); // 牛舍位置不一定有序,必须先排序,为后续贪心做准备
  • 详细分析:题目明确说明“不保证 x数组单调递增”。由于我们的贪心策略依赖于从左到右依次扫描牛舍,因此必须首先对牛舍位置进行升序排序。sort(a+1,a+n+1) 确保了数组的有序性,这是后续二分和贪心正确执行的前提。

2. 二分答案框架

	int ans=0;
	int L=1,R=a[n],mid=0; // 二分答案:最小距离的下界是1,上界是最大坐标差
	while(L<=R){
		mid=(L+R)/2;
  • 详细分析:这里对“最小距离”进行二分。下界 L=1(因为坐标是整数,最小距离至少为1),上界 R=a[n] (即最右端牛舍的坐标,这是理论上的最大可能距离)。mid 代表我们当前正在验证的“假设最小距离”。

3. 核心逻辑:贪心验证(Check过程)

		// 贪心验证:假设当前两头牛的最小距离为 mid,最多能放几头牛?
		int cnt=1; // 计数器:第一头牛默认放在第一个牛舍 a[1]
		int t=a[1]; // 记录上一头牛放置的位置
		
		for(int i=2;i<=n;i++){
			// 如果当前牛舍与上一头牛的距离 >= mid,说明可以放下一头牛
			if(a[i]-t>=mid){
				cnt++;
				t=a[i]; // 更新上一头牛的位置为当前牛舍
			}
		}
  • 详细分析:这是本题最核心的贪心策略。
    • 初始化:为了让后面的牛有尽可能大的空间,第一头牛必须放在最左边的牛舍 a[1]。此时计数器 cnt=1,上一头牛的位置 t 更新为 a[1]。
    • 线性扫描:从第二个牛舍开始遍历。对于每一个牛舍 a[i],我们检查它与“上一头已经放下的牛”(位置为 t)之间的距离。如果 a[i] - t >= mid,说明在这个牛舍放牛不会违反最小距离 mid 的限制。根据贪心思想,我们立刻把牛放在这里,并更新 t 为当前的 a[i]。
    • 为什么贪心是正确的? 因为牛舍是排好序的,如果当前牛舍 a[i] 可以放牛,而我们选择跳过它去放更右边的牛舍,只会让后续的牛空间变得更小(或不变),绝不会让能放下的牛更多。因此,能放就放是最优策略。

4. 二分区间的收缩与答案更新

		// 如果能放下的牛少于 m 头,说明 mid 太大了,需要减小距离
		if(cnt<m) R=mid-1;
		else{ // 如果能放下 m 头或更多,说明 mid 可行,尝试更大的距离
			ans=mid;
			L=mid+1;
		}
	}
	cout<<ans;
    return 0;
}
  • 详细分析:
    • 不满足条件(cnt < m):说明我们假设的最小距离 mid 太大了,导致牛舍之间隔得太开,连 mm 头牛都放不下。因此,我们需要缩小距离,将右边界 R 移动到 mid−1 。
    • 满足条件(cnt >= m):说明在最小距离为 mid 的情况下,我们至少能放下 m 头牛。这是一个可行的解,我们先用 ans 记录下这个 mid 。但是,题目要求“最大化”这个距离,所以 mid可能还不是最优的,我们尝试增大距离,将左边界 LL 移动到 mid+1 ,继续寻找更大的可行解。

核心逻辑总结表

代码模块核心变量/操作精炼作用解决的痛点
数据预处理sort(a+1,a+n+1)将无序的牛舍坐标升序排列为后续从左到右的贪心扫描提供有序的基础环境
二分框架L=1, R=a[n]对“最小距离”进行二分查找将复杂的“求最大值”问题转化为简单的“验证可行性”问题
贪心初始化cnt=1, t=a[1]默认第一头牛放在最左侧牛舍确立了贪心策略的起点,为后续牛留出最大空间
贪心验证if(a[i]-t>=mid)线性扫描,能放牛就立刻放下在限定距离 midmid 下,以最紧凑的方式测试最多能放多少头牛
单片机技术入门与实战:从零基础到项目开发 单片机(MCU)作为嵌入式系统的核心组件,集成了CPU、内存和各种接口电路,广泛应用于智能家居、工业控制和汽车电子等领域。其工作原理基于实时控制和低功耗设计,通过定时器、中断系统和通信接口等功能模块实现各种控制任务。在物联网和智能硬件快速发展的背景下,掌握单片机开发技术成为电子工程师的重要技能。本文以STM32和PIC系列为例,详细解析单片机的基本概念、功能模块和选型指南,并分享从入门到项目实战的系统学习方法,帮助开发者在3-6个月内快速掌握这一关键技术。 阅读详情

相关推荐

华为EC6108V9E刷机实战:从U盘准备到开机优化的完整避坑指南

本文提供华为悦盒EC6108V9E刷机与优化的完整实战指南。针对搭载RK3228芯片和安卓4.4.4系统的设备,从型号确认、固件选择、U盘准备,到详细刷机步骤、常见故障排除,以及刷机后的深度性能优化,手把手帮助用户规避风险,让旧盒子焕发新生,成为流畅的全能媒体中心。

weixin_29324401的博客 1196

进击的奶牛 Aggressive Cows G(洛谷- P1824 [USACO05FEB])

后来想到可以去二分每头牛之间的距离,当距离能塞下n头牛就增加距离 整个代码的核心在于if(cnt>=m) return 1,下面还会演示一个错误代码,if(cnt>m) return 1 这种就是错的,因为当能放下m头牛时,选择扩大还是减小距离非常重要,我们这道题求的是最大的最小距离,所以毫无疑问,我们需要当能放下m头牛时选择增加距离看还能不能放下。农夫约翰建造了一座有 n 间牛舍的小屋,牛舍排在一条直线上,第 i 间牛舍在 xi​ 的位置,但是约翰的 m 头牛对小屋很不满意,因此经常互相攻击。

布心老混子 所有代码均老混子本人远古手搓 易错点均为学生真实场景 博客文章部分借助ai生成 1153

RAG开源框架深度评测:从RAGFlow到Dify的实战选型指南

本文深度评测了主流RAG开源框架(RAGFlow、Dify、WeKnora)的核心能力与实战表现,提供企业级选型指南。重点对比了文档解析、检索性能和生产部署等关键指标,揭示RAGFlow在复杂文档处理、Dify在低代码开发、WeKnora在腾讯生态集成的差异化优势,并给出技术选型决策树与成本优化方案。

weixin_29294597的博客 828

题解:洛谷 P1824 [USACO05FEB] 进击的奶牛 Aggressive Cows G

题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。牛们并不喜欢这种布局,而且几头牛放在一个隔间里,它们就要发生争斗。约翰决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是多少呢?约翰为了防止牛之间互相伤害,因此决定把每头牛都放在离其它牛尽可能远的牛舍。也就是要最大化最近的两头牛之间的距离。头牛放入牛舍,使得任意两头牛之间的最小距离最大化。间牛舍的小屋,牛舍排在一条直线上,第。一行一个整数,表示最大的最小距离值。

团爸讲算法 231

【100%通过率】华为OD机试真题 Python 实现【打印机队列】【2022.11 Q4 新题】

有5台打印机打印文件,每台打印机有自己的待打印队列。因为打印的文件内容有轻重缓急之分,所以队列中的文件有1~10不同的代先级,其中数字越大优先级越高。打印机会从自己的待打印队列中选择优先级最高的文件来打印。如果存在两个优先级一样的文件,则选择最早进入队列的那个文件。现在请你来模拟这5台打印机的打印过程。

MISAYAONE的博客 1万+

对CryptoDriver里密钥格式定义的探索(1)

一入网络安全才发现深似海,传统汽车MCU码农转型之路异常艰难。在CP AUTOSAR中的CryptoDriver SWS对密钥格式的需求来源于RFC,其中要求了RSA、ECC、SHE等key material的格式。再往下看,我就有些迷糊了,例如关于RSA Private Key的OCTEE STRING格式根据IETF RFC8017,Public Key又得根据RFC5280,完全不得其解。所以今天先从生成密钥对,并对其进行解析开始,一步一步拆解。

认真搞搞汽车MCU 529

二分答案——【进击的奶牛问题】解析

农夫约翰要将 m 头牛放进 n 间直线排列的牛舍,需最大化任意两头牛间的最小距离。解题时先将牛舍位置排序,再用二分法查找可能的距离 d:左边界设为 1,右边界设为最大位置值,对中间值 mid 用 check 函数验证 —— 从第一个牛舍开始,统计间距≥mid 的牛舍数量,若数量≥m 则说明 mid 可行,尝试更大距离,否则缩小范围。

2403_89185994的博客 898

IDC 数据中心工程师面试题汇总

(适用于:IDC运维、机房值班、机房工程师、机柜运维、IDC基础设施、IDC网络运维岗)

老韩的Linux云计算架构师进阶之路 1086

洛谷 [USACO05FEB] 进击的奶牛 Aggressive Cows G

这题是二分+贪心的经典模板提。关键点:先排序;二分距离;贪心判断可行性。本题中,所有点两两之间的距离有一个最小值,题目要求使这个最小值最大化。

2401_86627848的博客 354

MATLAB - 利用非线性模型预测控制(Nonlinear MPC)来控制四旋翼飞行器

本示例展示了如何利用非线性模型预测控制(MPC)为四旋翼飞行器设计一个跟踪轨迹的控制器。

机器人控制与仿真应用 4435

15、分布式参数热交换器:建模、动态特性与控制

本文综述了分布式参数热交换器的建模、动态特性和控制方法。从热交换器的基本方程推导出发,探讨了一维流动、流动强迫、错流、螺旋和旋转再生式热交换器的建模方法,并分析了其动态行为和频率响应中的共振现象。同时,介绍了热交换器的模拟方法,包括数值模拟和近似方法,并讨论了多种控制策略,如常规控制、最优控制、数字控制以及自适应控制。最后,总结了热交换器研究的发展历程,并展望了未来的研究方向,包括建模精度提升、控制算法优化和跨学科融合等。

w8x9y0z1的博客 123

二分 洛谷P1824进阶奶牛(第一周)

农夫约翰建造了一座有n间牛舍的小屋,牛舍排在一条直线上,第i间牛舍在xi​的位置,但是约翰的m头牛对小屋很不满意,因此经常互相攻击。约翰为了防止牛之间互相伤害,因此决定把每头牛都放在离其它牛尽可能远的牛舍。也就是要最大化最近的两头牛之间的距离。牛们并不喜欢这种布局,而且几头牛放在一个隔间里,它们就要发生争斗。为了不让牛互相伤害。约翰决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是多少呢?

2601_95612197的博客 237

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

二分算法(优化)

在一个有序数组中查找一个数。每次考察数组当前部分的中间元素,如果中间元素刚好是要找的,就结束搜索过程;如果中间元素小于所查找的值,那么左侧的只会更小,不会有所查找的元素,只需到右侧查找;如果中间元素大于所查找的值,同理,只需到左侧查找。

2401_88036229的博客 458

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

视频隐私脱敏工程化:CSRT/KCF追踪算法在本地推理中的实现与边界

在短视频内容合规审查中,动态遮挡(Dynamic Masking)是高频且高耗时的环节。传统手动关键帧打码不仅效率低下,且在目标快速移动或遮挡时极易出现遮罩漂移。本文从计算机视觉工程角度,解析基于CSRT与KCF算法的目标追踪方案在视频隐私处理中的技术路径、性能权衡及落地实践。

Mysssone的博客 297

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

把 KV Cache 压到 FP4:BitDecoding-FP4 的算法-系统协同设计复盘

长上下文推理卡在KV Cache的显存与带宽上,而现有FP4方案要么精度崩、要么速度废。这篇文章复盘BitDecoding-FP4如何用三个算法补丁加一个系统重构,在B300上把服务吞吐提升2.4–3.0倍,精度几乎不掉。

helloagent的博客 308

【算法拾光】链表 哈希表|K个一组翻转链表 + 两数之和

K个一组翻转链表需分段反转,借助哑节点与前驱指针维护连接,避免断链;两数之和利用哈希表实现O(1)查找,空间换时间,高效定位目标组合。前者考察链表指针操作,后者聚焦映射关系构建,均为面试高频题。

wuqingyigexiaoba的博客 328

排序算法深度笔记(下):非比较类排序的线性突破与工程边界

排序算法时间复杂度额外空间复杂度稳定性是否基于比较选择排序O(N^2)(O(1))不稳定是冒泡排序O(N^2)(O(1))稳定是插入排序O(N^2)(O(1))稳定是归并排序O(N\log N)(O(N))稳定是快速排序O(N\log N)O(log N)不稳定是堆排序O(N\log N)O(1)不稳定是计数排序(O(N + M))O(M))稳定否基数排序O(N)稳定否桶排序平均O(N) / 最坏O(N^2)

2401_87069538的博客 601

优选算法:分治-归并排序

交易逆序对的总数

Wangshijie1015的博客 144

算法日常・每日刷题--<动态规划>42

本题为“不相交的线”,与最长公共子序列问题相似。使用动态规划求解:定义 dp[i][j] 表示 nums1[0:i] 与 nums2[0:j] 的最大不相交连线数。若元素相等,则继承左上值加1;否则取上方或左方最大值。最终返回 dp[m][n],即两数组的最大不相交连线数。时间复杂度 O(mn),空间复杂度 O(mn)。

2503_92261635的博客 23

408 算法 06|堆与 Top-K:最小的 10 个数,到底该用数组还是堆

2022(42) 找 100 万个数里最小的 10 个,官方给了"10 元素有序数组"和"大根堆"两种答案。我把两种都实现并数了比较次数:k=10 时两者几乎打平,k=10000 时堆少 111 倍。另附 2021(42) 计数排序的比较次数与稳定性实测。

m0_56226131的博客 418

408 算法 04|主元素与三元组最小距离:两种“扫描时做决定“的思路

2013(41) 的主元素用摩尔投票一遍选出候选,但真正的考点是"选完必须验票";2020(41) 的三元组最小距离,三指针每次只挪最小的那个,靠的是 D=2×(max−min) 这个恒等式。两套完整 C 代码加真实输出,附官方评分档位表。

m0_56226131的博客 417

牛客周赛165C题(前后缀性质,递推,排序,枚举)

题目大意:给定长度为 `n` 的数组,选择 `k ∈ [1,n]`,将前 `k` 个元素整体翻转,后面的元素不变。要求操作后的整个数组非递减,统计满足条件的 `k` 的数量。题目链接:https://ac.nowcoder.com/acm/contest/141721/C。时间复杂度:O(nlogn)

2501_94316951的博客 173

【MPC 算法】Python 实战:模型预测控制(MPC)算法原理与代码实现

本文介绍模型预测控制(MPC)原理与Python实现。MPC通过滚动优化预测未来状态,结合系统模型、目标函数与约束条件,动态生成最优控制序列。以一阶温度系统为例,使用CVXPY构建凸优化问题,实现加热功率的智能调控。代码包含模型预测、目标函数设计(含温度跟踪与控制平滑惩罚)、输入约束及滚动更新机制。仿真结果表明,MPC能快速稳定温度至目标值60℃,且控制动作平滑合理,体现其在复杂系统中的优越性。

赖德发的博客 39

算法61,判定是否为字符重排

两字符串能互为重排 ⇔。

sheshibenniaodan的博客 221

算法日常・每日刷题--<动态规划>32

给定严格递增的正整数数组,求最长斐波那契子序列长度。使用二维DP,dp[i][j]表示以arr[i]、arr[j]为最后两项的序列长度,初始化均为2。通过哈希表快速查找前一项target = arr[j] - arr[i],若存在且下标小于i,则状态转移:dp[i][j] = dp[k][i] + 1。遍历更新全局最大长度,最终若结果小于3则返回0。时间复杂度O(n²),空间复杂度O(n²)。

2503_92261635的博客 180

【前缀和+复合离散化】题解:双色矩形(two)_数据结构_算法优化_预处理_二维前缀和_STL_C++算法竞赛

给定一个 $n \times n$ 的黑白棋盘,初始按 $i+j$ 奇偶染色,经 $k$ 个格子颜色翻转后,求子矩形中黑白格子数差的绝对值最大值。由于 $n$ 可达 $10^9$,但 $k \leq 50$,可离散化关键点。枚举所有由修改点构成的矩形及其四边向外扩展(共 $16$ 种扩展方式),利用二维前缀和快速计算变化量,结合奇偶性判断多出的格子颜色,最终取最大绝对差。时间复杂度为 $O(k^4)$,在 $k \leq 50$ 下可行。

YLCHUP的博客 199
上一篇: P1030 [NOIP 2001 普及组] 求先序排列
下一篇: P9497 「RiOI-2」weight
谢天谢地AC了 | 信奥教练
博客等级 码龄1年 53粉丝 177原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值