旋转卡壳算法

计算几何系列 —— 美妙的旋转卡壳算法~上 上述就是我们利用旋转卡壳算法求出二维凸包的直径~,那么关于旋转卡壳算法如此巧妙,怎会只有这一种用途~ ,旋转卡壳算法其实还可以用于解决大量的多边形的问题,而非仅仅局限于原来了解的基于凸包的一些具体问题,十分具有研究价值 阅读详情

讲解见:http://www.cnblogs.com/Booble/archive/2011/04/03/2004865.html

实现:(在原有求凸包的基础上增加即可)

double cross(Pt a,Pt b,Pt c)//求叉积
{
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}

double dist2(Pt a,Pt b)//求距离
{
    Pt x=a-b;
    return (x.norm());//因为本题只要求求距离的平方所以没有开方
}
double rotating_calipers(Poly p)//旋转卡壳
{
    int j=1,n=p.pts.size();p.pts.push_back(p.pts[0]);
    double ans=0;
    for(int i=0;i<n;i++)
    {
        while(cross(p.pts[i],p.pts[i+1],p.pts[j])<cross(p.pts[i],p.pts[i+1],p.pts[j+1]))
            j=(j+1)%n;
        ans=max(ans,max(dist2(p.pts[i],p.pts[j]),dist2(p.pts[i+1],p.pts[j+1])));
    }
    return ans;
}

POJ2187:(跑得比暴力枚举O(n^2)还慢是什么鬼2333)

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include<iostream>
using namespace std;
const int MAXN = 50005;
const double EPS = 1e-8;

// 带误差比较
inline bool dcmp(double x, double y = 0)
{
    return fabs(x - y) <= EPS;
}

/*
 * 向量(Vector)或点
 *
 * 使用原点到一个点 (x, y) 的有向线段表示向量
 * 从点 A 到点 B 的向量表示为 A - B
 */
typedef struct Vec
{
    double x, y;

    Vec(double x = 0, double y = 0) : x(x), y(y) {}

    // 相加
    Vec operator+(const Vec &v) const
    {
        return Vec(x + v.x, y + v.y);
    }

    // 相减
    Vec operator-(const Vec &v) const
    {
        return Vec(x - v.x, y - v.y);
    }

    // 数乘(伸长、缩短)
    Vec operator*(double d) const
    {
        return Vec(x * d, y * d);
    }

    Vec operator/(const double d) const
    {
        return Vec(x / d, y / d);
    }

    // 范数,用来比较长度,等于长度的平方
    double norm() const
    {
        return x * x + y * y;
    }
} Pt;

// 点乘
double dot(const Vec &a, const Vec &b)
{
    return a.x * b.x + a.y * b.y;
}

// 叉乘
double cross(const Vec &a, const Vec &b)
{
    return a.x * b.y - a.y * b.x;
}

// 线段(Segment),用两个点表示
struct Seg
{
    Pt a, b;

    Seg(const Pt &a, const Pt &b) : a(a), b(b) {}

    // 线段包含点(点在线段上)
    bool include(const Pt &p)
    {
        // PA × PB = 0:PA 与 PB 共线,即点在线段所在的直线上
        // PA · PB = 0:PA 与 PB 方向不同(A 和 B 分别在 P 的两边),如果 PA · PB = 0 则 P = A 或 P = B
        return dcmp(cross(a - p, b - p)) && dot(a - p, b - p) <= 0;
    }
};

// 直线,用两个点表示
struct Line
{
    Pt a, b;

    Line() {} // 提供一个不需要参数的构造函数
    Line(const Pt &a, const Pt &b) : a(a), b(b) {}

    bool include(const Pt &p) const
    {
        return dcmp(cross(a - p, b - p));
    }

    // 两直线关系(交点个数)
    // 0 表示平行(无交点)
    // 1 表示相交(一个交点)
    // -1 表示重合(无数个交点)
    static int relation(const Line &a, const Line &b)
    {
        if (a.include(b.a) && a.include(b.b)) return -1;
        else if (dcmp(cross(a.b - a.a, b.b - b.a))) return 0;
        else return 1;
    }

    // 求两直线交点(需要保证两直线有交点)
    static Pt intersect(const Line &a, const Line &b)
    {
        double s1 = cross(b.a - a.a, b.b - a.a), s2 = cross(b.b - a.b, b.a - a.b);
        return a.a + (a.b - a.a) * s1 / (s1 + s2);
    }
};

// 求凸包用的点
int n;
Pt a[MAXN + 1];

// 凸包极角排序的比较函数
inline bool compare(const Pt &a, const Pt &b)
{
    // 两个向量
    Vec va = a - ::a[1], vb = b - ::a[1];
    double t = cross(va, vb);
    if (!dcmp(t)) return t > 0; // OA -> OB 是逆时针,则 A 极角序在先
    else return va.norm() < vb.norm(); // norm 较小的长度较小
}

struct Poly
{
    std::vector<Pt> pts;

    // 求凸包(Convex),结果储存在自身 pts 中
    void convex()
    {
        // 找出最左下角的点
        int id = 1;
        for (int i = 1; i <= n; i++)
        {
            if (a[i].x < a[id].x || (a[i].x == a[id].x && a[i].y < a[id].y)) id = i;
        }
        if (id != 1) std::swap(a[1], a[id]);

        // 排序
        std::sort(a + 2, a + n + 1, &compare);

        // 极角序扫描
        pts.push_back(a[1]);
        for (int i = 2; i <= n; i++)
        {
            // 比较,如果最后一个点需要被删掉则弹出(pop_back)
            while (pts.size() >= 2 && cross(a[i] - pts[pts.size() - 2], pts.back() - pts[pts.size() - 2]) >= 0) pts.pop_back();
            pts.push_back(a[i]);
        }
    }
};
double cross(Pt a,Pt b,Pt c)
{
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
//double cross(const Vec &a, const Vec &b)
//{
//    return a.x * b.y - a.y * b.x;
//}

double dist2(Pt a,Pt b)
{
    Pt x=a-b;
    return (x.norm());//因为本题只要求求距离的平方所以没有开方
}
double rotating_calipers(Poly p)
{
    int j=1,n=p.pts.size();p.pts.push_back(p.pts[0]);
    double ans=0;
    for(int i=0;i<n;i++)
    {
        while(cross(p.pts[i],p.pts[i+1],p.pts[j])<cross(p.pts[i],p.pts[i+1],p.pts[j+1]))
            j=(j+1)%n;
        ans=max(ans,max(dist2(p.pts[i],p.pts[j]),dist2(p.pts[i+1],p.pts[j+1])));
    }
    return ans;
}
int main()
{
    int i,j;
    cin>>n;
    for(i=1;i<=n;i++){
        scanf("%lf%lf",&a[i].x,&a[i].y);
    }
    Poly p;p.convex();
    cout<<(int)rotating_calipers(p)<<endl;

    return 0;
}
【算法模板】计算几何:旋转卡壳求凸包直径 旋转卡壳算法是一种几何算法,主要用于在二维平面上求解与凸包相关的最优问题。该算法利用凸包顶点的顺序性和对称性,通过模拟两个卡壳(calipers)沿着凸包边界的旋转来寻找最优解。常见的应用包括计算凸包的直径(即最远点对之间的距离)、最小包围矩形(最小面积矩形),以及最小宽度(宽度最小的方向)。 阅读详情

相关推荐

旋转卡壳算法(以poj 2187为例)

1.问题: 寻找凸多边形的直径。

记录走过的风风雨雨 1731

旋转卡壳——目录页

一些历史:1978年, M.I. Shamoss Ph.D. 的论文"Computational Geometry"标志着计算机科学的这一领域的诞生。 当时他发表成果的是一个寻找凸多边形直径的一个非常简单的算法, 即根据多边形的一对点距离的最大值来确定。 后来直径演化为由一对对踵点对来确定。 Shamos提出了一个简单的 O(n) 时间的算法来确定一个凸 n 角形的对踵点对。 因为他们最多只有

ACMaker的专栏 8229

旋转卡壳算法求最小外接矩形代码

/**MABR:Minimum Area Bounding Rectangle * @brief :获取由凸包传来的点集,计算最小外接矩形,采用旋转卡壳算法 * @param[in] :凸包传来的点集,逆时针顺序的点集 * @param[out] : * @return :返回最小外接矩形的四个点集。顺时针方向 */ CUBECOM_API vector<iCoord2d> GetMABRByRotatingCaliper(vecto..

qq_38409301的博客 2535

旋转卡壳算法总结

一、历史背景 1978年, M.I. Shamos's Ph.D. 的论文"Computational Geometry"标志着计算机科学的这一领域的诞生。 当时他发表成果的是一个寻找凸多边形直径的一个非常简单的算法, 即根据多边形的一对点距离的最大值来确定。 后来直径演化为由一对对踵点对来确定。 Shamos提出了一个简单的O(n)时间的算法来确定一个凸n角形的对踵点对。 因为他们最多只有 3n/2 对, 直径可以在O(n)时间内算出。 如...

Cloth的博客 3278

探索凸包算法:从斜率逼近到旋转卡壳

本文详细解读了在计算几何中用于求解凸包问题的多种算法,包括斜率逼近法、Jarvis算法和Graham算法,以及旋转卡壳技术在求解凸多边形直径、宽度和两个凸多边形间最大距离及最小距离问题中的应用。通过分析每种算法的原理、步骤和效率,揭示了它们在处理复杂问题时的优劣和适用场景。

weixin_35935514的博客 602

旋转卡壳算法讲解

1978年, M.I. Shamos's Ph.D. 的论文"Computational Geometry"标志着计算机科学的这一领域的诞生。 当时他发表成果的是一个寻找凸多边形直径的一个非常简单的算法, 即根据多边形的一对点距离的最大值来确定。 后来直径演化为由一对对踵点对来确定。 Shamos提出了一个简单的 O(n) 时间的算法来确定一个凸 n 角形的对踵点对。 因为他们最多只有 3n/2 对, 直径可以在 O(n) 时间内算出。 如同Toussaint后来提出的, Shamos的算法就像绕着多边形旋转一对卡壳。 因此就有了术语“旋转卡壳”。 1983年, Toussaint发表了一篇论文, 其中用同样的技术来解决许多问题。 从此, 基于此模型的新算法就确立了, 解决了许多问题。

计算凸包直径—旋转卡壳算法

文章出自:http://www.cppblog.com/staryjy/archive/2009/11/19/101412.html        旋转卡壳可以用于求凸包的直径、宽度,两个不相交凸包间的最大距离和最小距离等。虽然算法的思想不难理解,但是实现起来真的很容易让人“卡壳”。   拿凸包直径(也就是凸包上最远的两点的距离)为例,原始的算法是这样子:Compute the

每天进步一点 3720

AD9371实战:如何用ZCU106搭建JESD204B TX时钟链(含关键参数计算)

本文详细解析了如何基于Xilinx ZCU106开发板为AD9371搭建JESD204B TX时钟链。文章从系统需求出发,逐步推导出从IQ采样率到GTH线速率的关键参数计算公式,并提供了在Vivado中配置GTH收发器(包括QPLL选择、分频比设置)的实战步骤与调试技巧,旨在帮助硬件工程师快速实现稳定可靠的JESD204B高速数据传输链路。

weixin_29164843的博客 293

计算几何之旋转卡壳算法

转载于 http://blog.youkuaiyun.com/acmaker/article/details/3188177 一、目录 一些历史: 1978年, M.I. Shamos's Ph.D. 的论文"Computational Geometry"标志着计算机科学的这一领域的诞生。 当时他发表成果的是一个寻找凸多边形直径的一个非常简单的算法, 即根据多边形的一对点距离的最大值来

wangheng 1万+

DQN网络代码调用env.reset()后存储观测信息报错问题ValueError: setting an array element with a sequence.解决处理

**reset()函数返回的是一个array类型以及其中数据的type!模拟游戏进行学习任务。因此需要将observation指定为真正需要的array信息即可,得到的的变量observation类型与Agent存储时的。因此怀疑返回的observation有问题,于是通过。报错信息提示为数据维度不对应,也即最初通过。在强化学习DQN网络代码实现过程中,针对。

Vulcan_Q的博客 4092

Graybox Overview

Graybox功能使能够在sub_module上执行扫描和ATPG操作,然后能够在更高层次的层次上执行扫描和ATPG操作时使用该子模块的简化的Graybox表示,从而简化了分层设计中的扫描插入和ATPG操作过程。由于子模块的graybox表示只包含极少量的互连电路(子模块与top的互连),在大型分层设计中使用graybox可以极大地减少执行扫描插入,优化计时,分析故障和创建测试pattern所需的memory和工具runtime。

weixin_44954910的博客 1081

旋转卡壳算法(转载)

https://www.cnblogs.com/little-w/p/3579603.html 转自:http://blog.youkuaiyun.com/acmaker/article/details/3188177 一、目录 一些历史: 1978年, M.I. Shamos's Ph.D. 的论文"Computational Geometry"标志着计算机科学的这一领域的诞生。 当...

ako2654的博客 689

【架构】-- StarRocks 和 Doris 介绍与选型建议

查询性能 | ✅ 高性能,支持向量化执行和 CBO 优化器 | ✅ 高性能,优化的查询引擎 |- **实时性要求高**:如果业务对数据的实时性要求较高,建议选择 **StarRocks**,其在实时数据处理和低延迟查询方面表现优越。- **复杂查询需求**:对于需要处理复杂多表关联查询的场景,两者均可胜任,需根据具体性能测试结果进行选择。

欢迎来到我的博客,一起探索代码里的世界! 1831

旋转卡壳(卡尺)算法

申明,本文非笔者原创,原文转载自:http://hi.baidu.com/final_field/item/0c95a87c9299a65d0d0a07f0

计算机视觉小菜鸟的专栏 5250

Android CCodec (十七) 硬件解码调用分析-1(基于V4l2)

简单的分析V4L2DecodeComponent和其相关内容,后续针对解码调用单独分析。

给大佬递杯卡布奇诺的博客 6593

UG\NX二次开发 找不到指定的dlx文件(Specified Dlx file not found)

有群友问:用Ctrl+U运行的时候就报错,找不到指定的dlx文件Specified Dlx file not found。怎么处理。

王牌飞行员_里海的博客 1130

谈谈我对旋转卡壳算法本质的理解

我学很多东西的过程中,经常无法理解现有的资料的表述,感觉那些讲的太肤浅,最后靠自己推倒证明才能理解,旋转卡壳也是其中的一个…… 关于旋转卡壳的资料,大概有这几个: http://cgm.cs.mcgill.ca/~orm/rotcal.frame.html http://www.cppblog.com/staryjy/archive/2009/11/19/101412.html http:

金字塔 2462

基于YOLOv8的农作物病虫害检测系统设计与实现

国内如中国农业大学的科研团队采用改进的Faster R-CNN模型对小麦病害进行检测,取得了较好的效果。农作物病虫害是影响农业生产的重要因素之一,每年因病虫害导致的农作物减产高达20%-40%。YOLO(You Only Look Once)系列算法作为目标检测领域的代表性模型,以其高效、准确的特点在众多领域得到广泛应用。YOLOv8作为该系列的最新版本,在精度和速度上都有显著提升,非常适合农作物病虫害检测这类需要实时处理的应用场景。然而,现有研究仍存在一些不足:一是模型复杂度高,难以部署到移动设备;

YOLO 794
上一篇: Codeforces Round #476 (Div. 2) [Thanks, Telegram!]
下一篇: POJ3608(旋转卡壳求两个多边形最短距离)
HumveeA6
博客等级 码龄17年 12粉丝 175原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值