洛谷题目:P2742 [USACO5.1] 圈奶牛Fencing the Cows /【模板】二维凸包 题解 (本题较难)

题目传送门:P2742 [USACO5.1] 圈奶牛Fencing the Cows /【模板】二维凸包 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

另:由于一些文章的疏忽,导致一些错别字,代码错误,公式错误导致大家的理解和误导,到后期作者会进行更改,感谢大家!!!(如果有发现勘误请大家联系作者)

前言:

        本题涉及到计算几何、分治,凸包,这道题相对来说比较的难(对我来说一点都不难),可可能对那些计算几何、凸包的初学者理解起来较为抽象,刚好下一期的文章就是写关于计算机几何,凸包的知识分析与理解,帮助大家。

题目来自:

        题目来自USACO是美国计算机奥林匹克竞赛英文名:Wntied States of America Computing 

Olympiad的简称   这道题在洛谷里并没有却出明确的难度,作者自己评了一下,可以给到银级的难度。

1、题目分析:

        本题的目标是计算能够围住给定的 n 个放牧点的最短围栏长度。从几何角度来看,这个最短的围栏实际上就是这些点的凸包的周长。凸包是包含所有给定点的最小凸多边形,它的特点是凸包上的点使得多边形的内部角度都小于或等于 180 度。

2、Graham扫描算法:

        1、找到最下方的点:

                首先,我们需要找到所有点中 y 坐标最小的点,如果有多个点 y 坐标相同时,则选择其中 x 坐标最小的点。这个点将作为凸包构建的起始点,因为它一定是凸包上的点。

                在代码视线中,我们使用 sort 函数和 compare 函数来实现这一个目的。 compare 函数会将点集按照 y 坐标排序,如果 y 坐标相同,则按照 x 坐标排序这样第一个点就是我们要找的最下方的点。

        2、对其余点进行极角排序:

                对于除最下方点外的其余点,我们将它们按照相对于最下方点的极角进行排序。极角排序可以使用叉积来实现。叉积计算公式:

                        \overrightarrow{OA} \times \overrightarrow{OB}=(A_{x}-O_{x})*(B_{y}-O_{y})-(A_{y}-O_{y})*(B_{x}-O_{x})

                对于三个点 O、 A 和 B,如果叉积 cp (o,a,b)大于0,则B在OA的逆时针方向;如果等于0,则O、A、B共线;如果小于0,则B在OA的顺时针的方向。

                在 cl 函数中,先将所有点按照极角排序,排序依据是 cp 函数。

        3、构建凸包:

                我们使用一个栈(用vector<Point>模拟)来存储凸包上的点。

                首先我们将最下方的点和排序后的第二个点加入栈中。

                然后遍历上下的点,对于每个新点,检查它是否会使栈顶的点和栈顶前一个点构成的边向左转,即叉积大于0。

                如果不是向左转(叉积小于等于 0),则将栈顶元素弹出,直到新点使栈顶元素和栈顶前一个元素构成的边向左转或栈中元素数量小于 2。然后将新点加入栈中。这一过程会构建出凸包的下部分。

                为了构建上部分的凸包,我们从倒数第二个点开始,执行相同的操作,将点加入栈中,直到遍历完所有点。

                最后需要将最后一个重复添加的点从栈中弹出,因为在构建上凸包时会重复添加起始点。

        4、计算凸包周长:

                对于存储在 h 中的凸包上的点,使用 distance 函数计算相邻点之间的距离。

                distance 函数函数使用欧几里得距离公式:

                \sqrt{(x_{1}-x_{2})^{2}+(y_{1}-y_{2})^{2}} 来计算两点之间的距离。

                将所有相邻点的距离相加,最后加上最后一个点和第一个点之间的距离,就得到了凸包的周长,也就是最短围栏的长度。

3、输入、出处理:

        1、输入:

                首先从标准的输入读取一个整数 n ,表示点的数量。

                然后读取 n 行,每行包含一个点的 x 和 y 坐标。

        2、输出:

                计算出最短围栏长度(凸包周长)后,将结果保留并2位小数输出。

5、示例:

        假设我们输入为:

4
4 8
4 12
5 9.3
7 8
  1. 首先找到最下方的点,经过排序后是 (4, 8)
  2. 对其他点进行极角排序。
  3. 构建凸包,通过 cl 函数,得到凸包上的点序列。
  4. 使用 perimeter 函数计算凸包周长,最终将结果输出,保留两位小数。

6、代码:

#include <bits/stdc++.h>
using namespace std;
struct Point {
    double x;
    double y;
};
double cp(const Point& O, const Point& A, const Point& B) {
    return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);
}
bool c(const Point& p1, const Point& p2) {
    if (p1.y == p2.y) {
        return p1.x < p2.x;
    }
    return p1.y < p2.y;
}vector<Point> cl(vector<Point>& points) {
    int n = points.size();
    if (n <= 1) {
        return points;
    }
    sort(points.begin(), points.end(), c);
    vector<Point> hull;
    for (int i = 0; i < n; ++i) {
        while (hull.size() >= 2 && cp(hull[hull.size() - 2], hull.back(), points[i]) <= 0) {
            hull.pop_back();
        }
        hull.push_back(points[i]);
    }
    int lll = hull.size();
    for (int i = n - 2; i >= 0; --i) {
        while (hull.size() > lll && cp(hull[hull.size() - 2], hull.back(), points[i]) <= 0) {
            hull.pop_back();
        }
        hull.push_back(points[i]);
    }
    hull.pop_back(); 
    return hull;
}
double d(const Point& p1, const Point& p2) {
    double dx = p1.x - p2.x;
    double dy = p1.y - p2.y;
    return sqrt(dx * dx + dy * dy);
}
double pi(const vector<Point>& hull) {
    double p = 0;
    int n = hull.size();
    for (int i = 0; i < n - 1; ++i) {
        p += d(hull[i], hull[i + 1]);
    }
    p += d(hull[n - 1], hull[0]);
    return p;
}
int main() {
    int n;
    cin >> n;
    vector<Point> points(n);
    for (int i = 0; i < n; ++i) {
        cin >> points[i].x >> points[i].y;
    }
    vector<Point> h = cl(points);
    double l = pi(h);
    cout << fixed << setprecision(2) << l << endl;
    return 0;
}

总的来说其实这道题一点都不难的,虽然计算几何和凸包理解起来比较抽象,但是只要能理解,无论有多难,都是能啃下来的

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

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

相关文章

Qt中的按钮组:QPushButton、QToolButton、QRadioButton和QCheckBox使用方法(详细图文教程)

&#x1f4aa; 图像算法工程师&#xff0c;专业从事且热爱图像处理&#xff0c;图像处理专栏更新如下&#x1f447;&#xff1a; &#x1f4dd;《图像去噪》 &#x1f4dd;《超分辨率重建》 &#x1f4dd;《语义分割》 &#x1f4dd;《风格迁移》 &#x1f4dd;《目标检测》 &a…

2025-1-21 SUCTF 2025 crypto signin

今年充满期待&#xff0c;上线一看两道题&#xff0c;一道看名字应该是跟环相关的&#xff0c;估计做不出来&#xff0c;还有一道签到题&#xff0c;没做出来&#xff0c;遗憾下线 文章目录 signin signin from Crypto.Util.number import * from secret import flagbit_lengt…

C语言之图像文件的属性

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 图像文件属性提取系统设计与实现 目录 设计题目设计内容系统分析总体设计详细设计程序实现…

【Linux】华为服务器使用U盘安装统信操作系统

目录 一、准备工作 1.1 下载UOS官方系统 &#xff11;.&#xff12;制作启动U盘 1.3 服务器智能管理系统iBMC 二、iBMC设置U盘启动 一、准备工作 1.1 下载UOS官方系统 服务器CPU的架构是x86-64还是aarch64&#xff09;,地址&#xff1a;统信UOS生态社区 - 打造操作系统创…

macOS如何进入 Application Support 目录(cd: string not in pwd: Application)

错误信息 cd: string not in pwd: Application 表示在当前目录下找不到名为 Application Support 的目录。可能的原因如下&#xff1a; 拼写错误或路径错误&#xff1a;确保你输入的目录名称正确。目录名称是区分大小写的&#xff0c;因此请确保使用正确的大小写。正确的目录名…

python麻辣香锅菜品推荐

1.推荐算法概述 推荐算法出现得很早,最早的推荐系统是卡耐基梅隆大学推出的Web Watcher浏览器导航系统&#xff0c;可以根据当的搜索目标和用户信息,突出显示对用户有用的超链接。斯坦福大学则推出了个性化推荐系统LIRA.AT&T实验室于1997年提出基于协作过滤的个性化推荐系统…

利用大型语言模型在量化投资中实现自动化策略

“Automate Strategy Finding with LLM in Quant investment” 论文地址&#xff1a;https://arxiv.org/pdf/2409.06289 摘要 这个新提出的量化股票投资框架&#xff0c;利用大型语言模型&#xff08;LLMs&#xff09;与多智能体系统相结合的方法&#xff0c;通过LLMs从包括数…

JAVA:Spring Boot 实现责任链模式处理订单流程的技术指南

1、简述 在复杂的业务系统中&#xff0c;订单流程往往需要一系列的操作&#xff0c;比如验证订单、检查库存、处理支付、更新订单状态等。责任链模式&#xff08;Chain of Responsibility&#xff09;可以帮助我们将这些处理步骤分开&#xff0c;并且以链式方式处理每一个操作…

(开源)基于Django+Yolov8+Tensorflow的智能鸟类识别平台

1 项目简介&#xff08;开源地址在文章结尾&#xff09; 系统旨在为了帮助鸟类爱好者、学者、动物保护协会等群体更好的了解和保护鸟类动物。用户群体可以通过平台采集野外鸟类的保护动物照片和视频&#xff0c;甄别分类、实况分析鸟类保护动物&#xff0c;与全世界各地的用户&…

算法专题(三):二分查找

本篇还是像之前一样&#xff0c;以举例子的形式向大家讲解&#xff01;每道题的题目均是传送门&#xff01;点击跳转对应题&#xff01; 目录 一、二分查找 1.1 题目 1.2 思路 1.3 代码实现 总结&#xff08;模版&#xff09; 朴素版&#xff1a; 二、在排序数组中查找…

C# OpenCvSharp 部署文档矫正,包括文档扭曲/模糊/阴影等情况

目录 说明 效果 模型 项目 代码 下载 参考 C# OpenCvSharp 部署文档矫正&#xff0c;包括文档扭曲/模糊/阴影等情况 说明 地址&#xff1a;https://github.com/RapidAI/RapidUnDistort 修正文档扭曲/模糊/阴影等情况&#xff0c;使用onnx模型简单轻量部署&#xff0c…

Excel 技巧15 - 在Excel中抠图头像,换背景色(★★)

本文讲了如何在Excel中抠图头像&#xff0c;换背景色。 1&#xff0c;如何在Excel中抠图头像&#xff0c;换背景色 大家都知道在PS中可以很容易抠图头像&#xff0c;换背景色&#xff0c;其实Excel中也可以抠简单的图&#xff0c;换背景色。 ※所用头像图片为百度搜索&#x…

吴恩达深度学习——神经网络介绍

文章内容来自BV11H4y1F7uH&#xff0c;仅为个人学习所用。 文章目录 什么是神经网络引入神经网络神经元激活函数ReLU隐藏单元 用神经网络进行监督学习监督学习与无监督学习举例 什么是神经网络 引入 已经有六个房子的数据集&#xff0c;横轴为房子大小&#xff0c;纵轴为房子…

xctf-comment(Intruder,git恢复,SQL注入,Hex解码)

这题是2018年网鼎杯真题&#xff0c;考察 Burp Suite 的 Intruder 模块去找用户密码&#xff0c;使用 githacker 恢复代码&#xff08;githack不行&#xff09;&#xff0c;代码审计发现SQL二次注入&#xff0c;尝试SQL注入读取文件内容&#xff0c;读取的是/home/www/.bash_hi…

分布式系统通信解决方案:Netty 与 Protobuf 高效应用

分布式系统通信解决方案&#xff1a;Netty 与 Protobuf 高效应用 一、引言 在现代网络编程中&#xff0c;数据的编解码是系统设计的一个核心问题&#xff0c;特别是在高并发和低延迟的应用场景中&#xff0c;如何高效地序列化和传输数据对于系统的性能至关重要。随着分布式系…

C++《AVL树》

在之前的学习当中我们已经了解了二叉搜索树&#xff0c;并且我们知道二叉搜索树的查找效率是无法满足我们的要求&#xff0c;当二叉树为左或者右斜树查找的效率就很低下了&#xff0c;那么这本篇当中我们就要来学习对二叉搜索树进行优化的二叉树——AVL树。在此会先来了解AVL树…

ToDesk设置临时密码和安全密码都可以当做连接密码使用

ToDesk 在各领域办公都已经是非常常见了 为了安全 ToDesk 设置了连接密码&#xff0c;想连接 需要输入远程码和连接密码 我们刚打开 系统默认给我们用的是临时密码&#xff0c;安全性确实很强 和定时Tokey一样&#xff0c;固定时间切换。 但是 如果我们要经常连接这个电脑&a…

LLMs(大型语言模型)的多智能体:Auto-GPT

LLMs(大型语言模型)的多智能体:Auto-GPT 是指在一个系统中集成多个具有不同能力、角色和任务的智能体,这些智能体能够相互协作、沟通和交互,以共同完成复杂的任务或解决复杂的问题。每个智能体都可以被视为一个独立的实体,具有自己的策略、目标和知识库,通过相互之间的…

【Linux环境变量与命令行参数】常见环境变量 | 环境变量的全局属性 | 命令行参数

前言 本文中主要介绍PATH、HOME、SHELL、HISTSIZE这4个环境变量&#xff0c;其中详细介绍PATH。并理解环境变量的全局属性--环境变量可以被子进程继承&#xff0c;这里要注意和C中的继承进行区分。其次&#xff0c;介绍命令行参数--mian函数的参数。 1.环境变量的基本概念 在…

【Python】函数(二)

链式调用 # 判定是否是奇数 def isOdd(num):if num % 2 0:return Falseelse:return Trueresult isOdd(10) print(result)实际上也可以简化写作 print(isOdd(10))把一个函数的返回值, 作为另一个函数的参数, 这种操作称为 链式调用 嵌套调用 函数内部还可以调用其他的函数…