当前位置: 首页 > news >正文

洛谷P2742 【模板】二维凸包 / [USACO5.1] 圈奶牛Fencing the Cows

洛谷P2742 【模板】二维凸包 / [USACO5.1] 圈奶牛Fencing the Cows
题目大意
给定平面上 n 个点,求能围住所有点的最小凸多边形周长。
数据范围:1 ≤ n ≤ 10^5,坐标 |xi|, |yi| ≤ 10^6,小数点后最多两位。

分析
问题等价于求这些点的凸包周长。
n 较大,需要 O(n log n) 的凸包算法。
Andrew 算法是一种经典解法,通过排序和两次扫描得到凸包顶点,时间复杂度 O(n log n)。

Andrew 算法描述

  1. 排序:将所有点按 x 坐标为第一关键字、y 坐标为第二关键字升序排序。排序后的第一个点和最后一个点一定在凸包上。
  2. 构造下凸包:从最左到最右顺序扫描每个点,用栈维护当前凸包上的点。对于新点,不断检查栈顶两点与新点构成的向量的叉积,如果叉积 ≤ 0(表示新点在栈顶两点连线的右侧或共线),则弹出栈顶,直到满足左转关系,然后将新点入栈。
  3. 构造上凸包:从最右到最左逆序扫描每个点(排除已经用过的首尾点),同样用栈维护,但需保证栈大小不小于下凸包的点数,避免重复。扫描结束后,栈中存储了凸包的所有顶点(首尾重复一次)。
    最后,计算相邻顶点间的距离之和即得凸包周长。

代码解释(对应已给出的 AC 代码)
结构体 Point:存储点的 x, y 坐标。
叉积函数 cross(a, b, c):计算向量 ab 与 ac 的叉积,用于判断转向。若返回值 ≤ 0 表示在右侧或共线。
距离函数 dis(a, b):计算两点欧氏距离。
排序比较函数 comp:按 x 升序,x 相同则按 y 升序。
Andrew 函数:
传入点的数量 n 和栈顶指针初始值 0。
首先对所有点排序(下标从 1 开始)。
下凸包:遍历 i = 1 到 n,在栈中维护下凸包。当栈顶至少有两个点且新点与栈顶两点叉积 ≤ 0 时,弹出栈顶,然后将当前点入栈。
记录此时栈大小 t,表示下凸包的点数。
上凸包:从 i = n-1 到 1 逆序遍历,同样用栈维护,但需保证栈大小始终大于 t,以免破坏下凸包。条件仍然是叉积 ≤ 0 时弹出。
扫描结束后,栈中从 1 到 top-1 存储了凸包的所有顶点(首尾重复一次,即起点在栈中出现了两次)。
最后计算周长:遍历 i = 1 到 top-1,累加 ss[i] 到 ss[i+1] 的距离。
主函数 solve:
读入 n 和所有点坐标。
调用 Andrew 得到周长,保留两位小数输出。
时间复杂度
排序:O(n log n)
凸包扫描:每个点最多入栈两次、出栈两次,总操作 O(n)
总复杂度 O(n log n),在 n = 10^5 时完全可行。

总结
本题是凸包模板题,Andrew 算法实现简洁,利用叉积判断转向,通过两次扫描得到凸包顶点。注意处理共线情况时,题目通常要求凸包顶点不包含边上的中间点,因此弹出条件为 ≤ 0 而非 < 0。最终周长计算注意浮点数精度,保留两位小数输出

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define endl '\n'
#define fast ios::sync_with_stdio(0),cin.tie(0)
#define pll pair<ll,ll>
const ll N = 1e5 + 5;struct Point{double x,y;
}pp[N],ss[N];double cross(Point a, Point b, Point c){//叉乘return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
double dis(Point a, Point b){//距离return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}bool comp(Point a, Point b){//比较return a.x != b.x ? a.x < b.x : a.y < b.y;
}double Andrew(ll n, ll top){sort(pp + 1, pp + n + 1, comp);for(ll i = 1; i <= n; i++){//下凸包while(top > 1 && cross(ss[top - 1],ss[top],pp[i]) <= 0) top--;ss[++top] = pp[i];}ll t = top;for(ll i = n - 1; i >= 1; i--){//上凸包while(top > t && cross(ss[top - 1],ss[top],pp[i]) <= 0) top--;ss[++top] = pp[i];}double res = 0;for(ll i = 1; i < top; i++){res += dis(ss[i],ss[i + 1]);}return res;
}void solve(){ll n,top = 0;cin >> n;for(ll i = 1; i <= n; i++){cin >> pp[i].x >> pp[i].y;}double ans = Andrew(n,top);cout<<fixed<<setprecision(2)<<ans<<endl;return;
}int main(){fast;ll t = 1; //cin >> t;while(t--){solve();}return 0;
}
http://www.jsqmd.com/news/415813/

相关文章:

  • AI 原生应用开源开发者沙龙深圳站精彩回顾 PPT下载
  • 2026年不锈钢管薄壁管公司权威推荐:变径类管件、四通管件、圆形不锈钢管、塑料管件、异形不锈钢管、异径法兰管件选择指南 - 优质品牌商家
  • 2026年不锈钢管方管厂家权威推荐榜:卫生级不锈钢管、双相不锈钢管、变径类管件、四通管件、圆形不锈钢管选择指南 - 优质品牌商家
  • YOLO X Layout常见问题解决:置信度阈值调整技巧
  • 美股、加拿大、墨西哥、秘鲁等股票实时行情数据获取指南
  • EasyAnimateV5-7b-zh-InP在网络安全领域的应用:威胁可视化系统
  • 2026年不锈钢管圆管厂家最新推荐:焊接不锈钢管、焊接接头管件、矩形不锈钢管、碳钢管件、螺纹接头管件选择指南 - 优质品牌商家
  • Qwen3-ASR-1.7B:22种中文方言识别实测体验
  • 小白友好!Z-Image-Turbo_Sugar脸部Lora快速入门指南
  • 2026年双相不锈钢管公司权威推荐:异径法兰管件、异径管件、支撑类管件、方形不锈钢管、无缝不锈钢管、法兰管件选择指南 - 优质品牌商家
  • 2026年不锈钢管异型管公司权威推荐:304/304L不锈钢管、316L不锈钢管、不锈钢管方管、不锈钢管管件选择指南 - 优质品牌商家
  • AI应用架构师如何设计智能运维系统的根因分析架构?流程+工具
  • AI安全测试:如何进行模型鲁棒性测试?
  • 2026年卫生级不锈钢管厂家权威推荐榜:矩形不锈钢管/碳钢管件/螺纹接头管件/装饰用不锈钢管/铸铁管件/选择指南 - 优质品牌商家
  • GLM-4.7-Flash实操手册:模型微调数据准备、LoRA适配器加载与热切换
  • TMSpeech:Windows实时语音转写高效解决方案全流程指南
  • 美胸-年美-造相Z-Turbo使用技巧:提升生成图片质量
  • WarcraftHelper:让经典RTS重获新生的兼容性优化方案
  • PDF-Extract-Kit-1.0保姆级教程:从安装到提取PDF内容
  • 手把手教学:用Step3-VL-10B实现图片内容分析与风格识别
  • ZTE ONU设备管理效率革命:从重复劳动到智能运维的技术实践
  • GTE中文向量模型性能实测:速度与精度双优
  • DouyinLiveRecorder海外直播录制卡顿问题深度优化指南
  • 实时手机检测-通用模型MySQL数据库集成方案
  • 2026年装饰用不锈钢管厂家最新推荐:304/304L不锈钢管/316L不锈钢管/不锈钢管管件/不锈钢给水管/选择指南 - 优质品牌商家
  • 2026年316L不锈钢管厂家推荐:无缝不锈钢管、焊接不锈钢管、焊接接头管件、矩形不锈钢管、碳钢管件选择指南 - 优质品牌商家
  • TGDZcalc by Groovy5 (41th)
  • CF E. Destroy it!
  • 如何通过Sunshine实现低延迟跨平台游戏串流?开源解决方案完整指南
  • 2026年圆形不锈钢管厂家推荐:304/304L不锈钢管/三通管件/不锈钢管无缝管/不锈钢管管件/卡箍接头管件/选择指南 - 优质品牌商家