算法-扫描线

目录

什么是扫描线算法?

扫描线简单应用

更多的扫描线


什么是扫描线算法?

        在计算几何中,扫描线算法(scan line algorithm)一般用来解决几何图形的面积交并,周长交并问题,扫描线算法的核心思想是利用扫描线(通常是水平线或垂直线)在几何空间中“扫描”对象,以确定哪些对象与扫描线相交。

        下面我们就来通过求矩形的面积并来介绍扫描线算法。先来看看怎么求下面图形的面积并:

        传统算法是两个矩形面积相加减去重合的面积:

(20−10)∗(20−10)+(25−15)∗(25.5−15)−(20−15)∗(20−15)=180.0

        但是这样算非常的耗费时间,因为每个矩形都需要两两配对,查看互相之间是否有交集。 

        那么我们接下来就想着把矩形分成三部分:

 

于是现在就变成了

( 20 − 10 ) ∗ ( 15 − 10 ) + ( 25.5 − 10 ) ∗ ( 20 − 15 ) + ( 25.5 − 15 ) ∗ ( 25 − 20 ) = 180 

        采取这个方法的好处就是只需要从左往右扫,一步一更新即可,而这个从左往右,或者从下往上扫的思想就是扫描线。


扫描线简单应用

        我们看看上面的图,显然,计算面积需要两个信息

  1.         每个新矩形的的高度。
  2.         每个新矩形的宽度。

        那么我们先从计算宽度说起,其实计算宽度很简单。我们把垂直于x的边单独挑出来然后按照x的大小排个序,隔位相减就可以得到。如kuan[0] = 15 - 10; kuan[1] = 20 -15;......

        然后来计算矩形的高度,这是整个扫描线最难理解的地方。

        首先思考一个问题:为什么二号矩形的高是(10+(25.5−10))呢?很直观的回答就是:那是因为得算上1号矩形高,再加上2号矩形多出来的部分

        那为什么三号矩形的高是(25.5−5)呢?那是因为得用2号矩形的高那部分减去,减掉2号矩形下面多出来的部分 

        那为什么有时候“多出来”是加上一个值,有时候“多出来”是减掉一个值呢?这个问题其实也是得到高度最核心的问题,就是“入边”和“出边”的问题。

        定义:在同一个矩形内,从左往右看,第一条看到的边为“入边”,第二条看到的边为“出边”其实所谓的从左往右(也可以是从上往下),就是扫描线的方向。当从左往右扫,遇到入边的线,则对入边区间扫到进行+1操作,遇到出边,那么对出边区间进行-1操作,这样子就可以解释“有时候“多出来”是加上一个值,有时候“多出来”是减掉一个值”这个问题了

        凭借这个知识,我们来思考步骤

  1. 第一条为入边,区间为[10,20],则区间[10,20] +1(此时区间[10,20] = 1)
  2. 查看整个域的区间,只有[10,20]有值,则Kuan[0]*10 = 50
  3. 第二条边为入边,区间为[15,25.5],则[15,25.5]+1(此时区间[10,15]=1,[15,20]=2,[20,25.5]=1)
  4. 查看整个域区间,从[10,25.5]有值,则Kuan[1]*(25.5-10) = 77.5
  5. 第三条边为出边,区间从[10,20],则[10,20]-1(此时区间为[15,25.5] = 1)
  6. 查看整个区间,从[15,25.5]有值,则Kuan[2]*(25.5-15) = 52.5
  7. 第四条边为出边,区间从[15,25.5],此时-1,区间值变为0
  8. 区间无值,遍历结束。

        这时候问题就来了,总所周知,下标可存不了25.5,而且它这个区间要是特别大,数组会存不下。这时候就可以用离散化来存放下标。

        我们把y坐标离散化用一个区间数组记录每个区间的值:于是现在[10,15]成为块1,[15,20]成为块2,[20,25.5]成为块3。则现在更新第一条入边[10,20]就变成更新[1,3],更新第二条边就变成更新[2,4],之后再查表全部乘起来即可。

        建立一个线段树,用一个cover表示区间[left,right]被覆盖的次数,用len表示这个区间的合法长度,那query(1到n)的合法长度,自然就能返回总共的区间长度了。

int cover[maxn];//存放i节点对应覆盖情况的值
double length[maxn];//存放区间i下的总长度
double yy[maxn];//存放离散后的y值

        仔细观察,这棵树似乎和之前的线段树不一样,它的叶子节点的[l,r]不相等,而是差别为1。
这是因为点对于求面积的题目毫无意义,我们最需要的是它每一个基础的“块”。

        1.第一条为入边,区间为[1,3],则区间cover[1,3] +1(此时区间[1,3] = 1)

        2.query整个域的区间,得到len=10,则sum += Kuan[0]*10 = 50,消去len

        3.第二条边为入边,区间为[2,4],则cover[2,4]+1(注意:这里只需要上推len,不需要下推cover至[2,3]和[3,4],也不需要上推cover至[1,4]。只要找到对应结点的区间能完全覆盖当前线段区间就可以回溯统计了,并不需要更新到叶子节点,这是线段树为什么效率高的原因)

        4.query整个区间,得到len = 15.5,则sum += Kuan[1]*(25.5-10) = 77.5,消去len

        5.第三条边为出边,区间从[1,3],则[1,3]-1

        6.query整个区间,得到10.5,则sum += Kuan[2]*10.5 = 52.5,消去len

        7.第四条边为出边,区间从[15,25.5],此时-1,整个区间没掉

        8.query整个区间,值为0,遍历结束。

        此时sum = 50 + 77.5 + 52.5 = 180,答案正确,这就是线段树用来解决矩形面积并的基本思路了。


更多的扫描线

        除了矩形,三角形,梯形,圆这些几何图形的面积并也可以用扫描线求出。因为扫描线算法的思想其实接近于微积分,即求出每个单位内的微分作积,而求任何几何图形的面积,在数学里我们使用的最多的就是微积分的方法,计算几何中,我们也常常使用自适应辛普森积分公式,格林公式等微积分的方法来求相关值,所以扫描线算法这种模拟微分也是可以的,并且精度方面占点优势:

        等腰三角形的扫描线模型:

        圆离散后的扫描线模型:

        辛普森公式:

        格林公式:

        辛普森积分:

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

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

相关文章

SAPUI5基础知识3 - 引导过程(Bootstrap)

1. 背景 在上一篇博客中,我们已经建立出了第一个SAPUI5项目,接下来,我们将为这个项目添加引导过程。 在动手练习之前,让我们先解释一下什么引导过程。 1.1 什么是引导过程? 在计算机科学中,引导过程也称…

5、css3 自动动画渐变背景

效果例图&#xff1a;&#xff08;因gif图片太大&#xff0c;而csdn只能上传小于5m图片&#xff0c;所以无法上传&#xff09; 1、首先上传html代码&#xff1a; <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8">&l…

【鸟哥】Linux笔记-硬件搭配

在Linux这个系统当中&#xff0c;几乎所有的硬件设备文件都在/dev这个目录内。打印机与软盘呢&#xff1f;分别是/dev/lp0, /dev/fd0。 几个常见的设备与其在Linux当中的文件名&#xff1a; 如果你的机器使用的是跟网际网络供应商 &#xff08;ISP&#xff09; 申请使用的云端…

二叉树的构建和遍历(oj题)

一、题目链接 https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId60&&tqId29483&rp1&ru/activity/oj&qru/ta/tsing-kaoyan/question-ranking 二、题目思路 利用先序遍历的方法&#xff0c;构建二叉树。为了保证在递归中&#xf…

USB主机模式——Android

理论 摘自&#xff1a;USB 主机和配件概览 | Connectivity | Android Developers (google.cn) Android 通过 USB 配件和 USB 主机两种模式支持各种 USB 外围设备和 Android USB 配件&#xff08;实现 Android 配件协议的硬件&#xff09;。 在 USB 主机模式下&#xff0…

Redis 中的 Zset 数据结构详解

目录 用法 1. 增 2. 删 3. 查 4. 交&#xff0c;并 编码方式 应用场景 Redis 中的 Zset&#xff08;有序集合&#xff09;是一种将元素按照分数进行排序的数据结构。与上篇写的SetRedis 中的 Set 数据结构详解不同&#xff0c;Zset 中的每个元素都关联一个浮点数类型的…

Jmeter的线程组之间传递参数

使用jemter做接口测试&#xff0c;有时候需要会遇到不同线程组之间调用相同变量的情况&#xff0c;最多见的就是token的传递&#xff0c;网上有很多处理方法&#xff0c;这里只记录setProperty的办法&#xff0c;一招鲜走遍天&#xff01; 首先我有两个线程组&#xff1a; 线程…

vm:为虚拟机配置多个虚拟网卡(ubuntu20.04)

前言&#xff1a; 环境&#xff1a;虚拟机 ubuntu 20.04 要求&#xff1a;如标题&#xff0c;但是这里针对的是 ubuntu 20.04&#xff0c;对于其他操作系统&#xff0c;可以找一下其他操作系统对应的配置文件是什么 vm 添加虚拟网卡 首先进入 vm&#xff1a; 点击设置&#xf…

JVM监控-JMX探针的安装和使用

jvm监控的搭建和使用 ​ Java Management Extensions&#xff08;JMX&#xff09;是一种Java标准&#xff0c;用于管理和监控Java应用程序&#xff0c;特别是分布式系统。它提供了一种标准化的方式来管理应用程序的各种方面&#xff0c;包括性能监控、配置更改、事件通知等。目…

nodemcu32s 和 mini D1 组局域网并用 webSocket 通信

实现思路 使用 mini D1 来搭建一个 webSocket 服务&#xff0c;然后使用 nodemcu32 连接&#xff0c;然后就可以进行通信了。 服务端代码&#xff08;mini D1&#xff09; 在代码中主要是需要控制好 loop 函数中的延时&#xff0c;也就是最后一行代码 delay&#xff0c;如果…

JS-51-Node.js10-yarn

一、yarn的简介 Yarn 是一款 JavaScript 的包管理工具&#xff08;npm的代替方案&#xff09;&#xff0c;是 Facebook, Google, Exponent 和 Tilde 开发的一款新的 JavaScript 包管理工具。 正如 Yarn 官网的介绍&#xff0c;Yarn 的具有速度快 、安全 、可靠 的优点&#x…

MathType2025数学公式编辑器有哪些新增功能?

在当今科技飞速发展的时代&#xff0c;数学、科学和工程教育领域对于精确性和效率的要求日益增高。随着教育数字化的不断深入&#xff0c;传统的教学方式和科研手段正逐渐被新型的数字工具所取代。在这一过程中&#xff0c;MathType作为一款强大的数学公式编辑器&#xff0c;其…

多维时序 | Matlab实现SA-BP模拟退火算法优化BP神经网络多变量时间序列预测

多维时序 | Matlab实现SA-BP模拟退火算法优化BP神经网络多变量时间序列预测 目录 多维时序 | Matlab实现SA-BP模拟退火算法优化BP神经网络多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现SA-BP模拟退火算法优化BP神经网络多变量时间序列预…

React-组件通信

组件通信 概念&#xff1a;组件通信就是组件之间的数据传递&#xff0c;根据组件嵌套关系的不同&#xff0c;有不同的通信方法 父传子 基础实现 实现步骤&#xff1a; 1.父组件传递数据-在子组件标签上绑定属性 2.子组件接收数据-子组件通过props参数接收数据 props说明 1.…

哪个牌子的无线麦克风好用?全网揭秘无线麦克风一拖二哪个牌子好

​在浩瀚的音频产品海洋中&#xff0c;如何挑选一款适合自己的无线领夹麦克风&#xff1f;这确实是一个值得深思的问题。今天&#xff0c;我为你精心推荐这几款无线领夹麦克风&#xff0c;它以其卓越的音质、稳定的性能和便捷的无线连接&#xff0c;赢得了众多用户的青睐。无论…

独家首发 | 基于多级注意力机制的并行预测模型

基于Transformer-BiGRUGlobalAttention-CrossAttention的并行预测模型! 往期精彩内容&#xff1a; 时序预测&#xff1a;LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较-CSDN博客 VMD CEEMDAN 二次分解&#xff0c;Transformer-BiGRU预测模型-CSDN博客 独家原创 | 基…

机器学习算法手撕(一):KD树

import math import matplotlib.pyplot as pltclass Node:def __init__(self, data, leftNone, rightNone):self.data dataself.left leftself.right right# 创建KDTree类 class KDTree:def __init__(self, k):self.k kdef create_tree(self,dataset,depth):if not dataset…

辅导男朋友转算法岗的第2天|self Attention与kv cache

文章目录 公式KV CacheMHA、MQA、GQA 面试题为什么除以 d k \sqrt{d_k} dk​ ​Multihead的好处decoder-only模型在训练阶段和推理阶段的input有什么不同&#xff1f;手撕必背-多头注意力 公式 $ \text{Output} \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) \times …

C#,JavaScript实现浮点数格式化自动保留合适的小数位数

目标 由于浮点数有漂移问题&#xff0c;转成字符串时 3.6 有可能得到 3.6000000000001&#xff0c;总之很长的一串&#xff0c;通常需要截取&#xff0c;但按照固定长度截取不一定能使用各种情况&#xff0c;如果能根据数值大小保留有效位数就好了。 C#实现 我们可以在基础库里…

【错题集-编程题】过桥(BFS)

牛客对应题目链接&#xff1a;过桥 (nowcoder.com) 一、分析题目 类似层序遍历的思想。 二、代码 //值得学习的代码 #include <iostream>using namespace std;const int N 2010;int n; int arr[N];int bfs() {int left 1, right 1;int ret 0;while(left < right)…