[BZOJ1185][HNOI2007]最小矩形覆盖(旋转卡壳)

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

=== ===

这里放传送门

=== ===

题解

这题好!踏!马!难!写!啊。。
可以发现最小覆盖矩形一定有一条边在凸包上,那么如果按顺序枚举凸包上的一条边,可以用旋转卡壳求出和它平行并且也卡在凸包上的另一条边;对于矩形的另外两条边,可以发现随着按顺序的枚举,它们两个也是跟着一起转的。那么从第一个点开始枚举点 p1 ——实际上是在枚举 p1 跟它下一个点构成的边A,然后找到跟它平行的卡在凸包上的边B——这个就是旋转卡壳的最简单的应用啦。然后考虑那两个跟它们垂直的直线,以下面这个图为例:
这里写图片描述
分别在两条直线如何找到跟它们两个垂直并且能够覆盖所有点的直线呢?显然我们应该在某一个范围内枚举点,比如说如果要求C这条直线的位置,我们就应该按照逆时针 p1→p2 的顺序来枚举点。而因为这条直线要求和A垂直,那么它的斜率就确定了。

然后就剩下一个要求就是这个直线和A,B组成的矩形一定要覆盖所有点。那这个怎么办呢?从图上我们可以发现一个很有用的性质就是C和A交点的横坐标在旋转的过程中是单峰的,在恰好覆盖所有点的时候取最值。
那到底是最大值还是最小值呢。。。。。一开始以为C就是要最大值D就是要最小值,实际上当 p1 这个点在下凸壳上的时候确实是C取Max,D取Min,但是当 p1 这个点旋转到上凸壳上的时候判定会发生变化,C变成了取Min,D变成了取Max。所以在求凸包的时候要记录上下凸壳的分界点用来判断。还有一个就是当C和D跟y轴垂直的时候交点的横坐标是不变的,这个时候就要改成判定纵坐标。

代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inc(x)((x==N)?1:x+1)
using namespace std;
const double eps=1e-10;
const double inf=1e60;
int n,m,k;
double ans;
struct Vector{
    double x,y;
    Vector (double X=0,double Y=0){x=X;y=Y;}
    Vector operator + (const Vector &a){return Vector(x+a.x,y+a.y);}
    Vector operator - (const Vector &a){return Vector(x-a.x,y-a.y);}
    double operator * (const Vector &a){return x*a.y-y*a.x;}
    Vector mul(double t){return Vector(x*t,y*t);}
    void read(){scanf("%lf%lf",&x,&y);}
    void print(){printf("%.5lf %.5lf\n",x,y);}
}p[50010],c[50010],a1,a2,a3,a4;
struct Line{
    Vector P,v;
    Line(){P=Vector();v=Vector();}
    void get(Vector A,Vector B){P=A;v=B-A;}
};
int comp(Vector a,Vector b){return a.x<b.x||(a.x==b.x&&a.y>b.y);}//注意点的排序
Vector GLI(Line a,Line b){
    Vector u=a.P-b.P;
    double t=(b.v*u)/(a.v*b.v);
    return a.P+a.v.mul(t);
}
void ConvexHull(){
    sort(p+1,p+n+1,comp);
    for (int i=1;i<=n;i++){
        while (m>1&&(c[m]-c[m-1])*(p[i]-c[m-1])<eps) --m;
        c[++m]=p[i];
    }
    k=m;
    for (int i=n-1;i>=1;i--){
        while (m>k&&(c[m]-c[m-1])*(p[i]-c[m-1])<eps) --m;
        c[++m]=p[i];
    }
    if (n>1) --m;
}
bool better(Vector a,Vector b){
    return (b.y-a.y>eps)||(fabs(b.y-a.y)<eps&&b.x-a.x>eps);
}
void Update(Line A,Line B,Vector P,Vector Q){
    Line C,D;
    Vector t[5];
    double ar;
    int rec;

    C.v=D.v=Vector(-A.v.y,A.v.x);
    C.P=P;D.P=Q;
    t[1]=GLI(C,A);t[2]=GLI(A,D);
    t[3]=GLI(D,B);t[4]=GLI(B,C);
    ar=fabs((t[2]-t[1])*(t[3]-t[1]))+fabs((t[3]-t[1])*(t[4]-t[1]));
    ar/=2;
    if (ans-ar>eps){
        ans=ar;rec=1;
        for (int i=2;i<=4;i++)
          if (better(t[i],t[rec])) rec=i;
        a1=t[rec];rec=rec%4+1;
        a2=t[rec];rec=rec%4+1;
        a3=t[rec];rec=rec%4+1;
        a4=t[rec];rec=rec%4+1;
    }
}
bool check(Line A,int now,int opt){
    Line T1,T2;
    Vector ip1,ip2;
    T1.P=c[now];T1.v=Vector(-A.v.y,A.v.x);
    T2.P=c[now+1];T2.v=T1.v;
    ip1=GLI(T1,A);ip2=GLI(T2,A);
    if (opt==0) return (ip1.x-ip2.x>eps||(fabs(ip1.x-ip2.x)<=eps&&ip2.y-ip1.y>eps));
    else return (ip2.x-ip1.x>eps||(fabs(ip1.x-ip2.x)<eps&&ip1.y-ip2.y>eps));
}
void Rotating_Calipers(int N){
    if (N==1){ans=0;a1=a2=a3=a4=c[1];return;}
    if (N==2){
        ans=0;
        if (better(c[2],c[1])) swap(c[1],c[2]);
        a1=a2=c[1];a3=a4=c[2];
        return;
    }
    int p1=1,p2=inc(p1),p3,p4,r0=0,r1=1;
    Line A,B;
    while (p1<=N){
        while ((c[p1+1]-c[p1])*(c[p2+1]-c[p2])>eps)
          p2=inc(p2);//找到能被当前这条边卡住的点
        A.get(c[p1],c[p1+1]);
        B.get(c[p2],c[p2]+A.v);
        if (p1==1){p3=p2;p4=p1;}//对另外两个点进行初始化
        if (p1==k) swap(r0,r1);//注意当旋转到上凸壳以后判断条件要更改
        while (p3!=p1&&check(A,p3,r0))
          p3=inc(p3);
        while (p4!=p2&&check(A,p4,r1))
          p4=inc(p4);
        Update(A,B,c[p3],c[p4]);
        ++p1;
    }
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) p[i].read();
    ConvexHull();
    ans=inf;
    Rotating_Calipers(m);
    printf("%.5lf\n",ans);
    a1.print();a2.print();a3.print();a4.print();
    return 0;
}

偏偏在最后出现的补充说明

旋转卡壳本质上就是利用了凸包上的单调性。
凸包上有很多很多单调性哟

多边形的最小外接矩形 该代码可用于求取一个多边形的最小外接矩形 立即下载

相关推荐

【点云语义分割】Ubuntu20.04下RangeNet++环境配置与实战指南

本文详细介绍了在Ubuntu20.04系统下配置和运行RangeNet++点云语义分割模型的完整实战指南。内容涵盖从Cuda、cudnn到TensorRT的深度学习环境搭建,RangeNet++源码编译的详细步骤与常见问题解决,以及如何运行首个分割Demo并可视化结果。最后,还探讨了处理自定义点云数据格式和进行性能调优的进阶技巧,旨在帮助开发者和研究者快速部署并应用这一先进的点云语义分割技术。

rnn9storyteller的博客 516

求散点最小覆盖矩形(凸包最小外接矩形)

问题描述: 给一堆散点,要求一个最小面积的矩形能覆盖所有的散点。 思路: 先散点建立凸包,然后用旋转卡壳的思想枚举边,枚举到每条边时,再找对应的最左、最右、最上方的一个点,这些点一定在外接矩形上,找到面积最小的矩形即可。 例题:最小矩形覆盖 #include<bits/stdc++.h> #define ll long long #define lf double #define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0

Khasehemwy的博客 2093

CentOS8安装NVIDIA显卡驱动、CUDA和Anaconda

CentOS8安装NVIDIA显卡驱动和CUDA 参考:CentOS nvidia+cuda+cudnn 安装 安装英伟达显卡驱动 1、检查是否安装了NVIDIA的GPU(硬件层面): lspci | grep -i nvidia 2、安装GCC、kernal组件、dkms等 sudo yum install gcc sudo yum install gcc-c++ sudo yum -y install kernel-devel sudo yum -y install kernel-headers s

智慧的旋风的博客 1万+

UVA 10173 Smallest Bounding Rectangle (旋转卡壳最小面积外接矩形)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1114 题意:求给定点集的最小面积外接矩形。 思路:模板(见我博客内)。 #include #include #include #include #define min(x,y) ((

whyorwhnt的专栏 1591

Abaqus梁模型仿真中的常见陷阱与优化策略

本文深入探讨了Abaqus梁模型仿真中的常见陷阱与优化策略,涵盖几何建模、材料属性设置、边界条件处理等关键环节。针对梁截面方向定义、网格划分、复合截面建模等典型问题,提供了实用的Python脚本示例和优化方案,帮助工程师避免计算错误并提升仿真精度。文章特别强调了动力分析中的网格密度要求和材料非线性考虑,为复杂工程应用提供专业指导。

weixin_29099217的博客 461

别再用Python卷了!用Matlab的Deep Learning Toolbox快速上手U-Net图像分割(附完整数据集处理代码)

本文介绍了如何使用Matlab的Deep Learning Toolbox快速上手U-Net图像分割,包括数据准备、网络构建、训练监控和模型应用等完整流程。Matlab的高度集成工具链和图形化界面为图像分割任务提供了更快捷、直观的解决方案,特别适合研究人员和工程师快速实现原型验证。

weixin_29927965的博客 382

HDU 5251 矩形面积 (最小矩形覆盖 凸包+旋转卡壳 详解 推荐)

HDU 5251 矩形面积 (最小矩形覆盖 凸包+旋转卡壳 详解 推荐)

Tc的专栏 1640

使用 C# 实现大华监控摄像头的控制与数据处理

本文介绍了使用C#调用大华SDK(DHNetSDK.dll)开发监控系统的方法。主要内容包括:开发准备、DLL引用设置、SDK初始化与设备登录、视频预览窗口嵌入、云台控制、抓图录像等核心功能实现。通过P/Invoke技术封装SDK接口,开发者可以快速构建具有视频监控、设备控制功能的C#应用程序。文中还提供了代码示例、常见问题解决方案,以及视频帧智能分析的扩展建议,为开发大华监控系统的二次应用提供了完整的技术指南。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1280

HDU 5251 矩形面积 (计算几何+旋转卡壳求覆盖凸包的最小矩形面积)

小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少。 Input 第一行一个正整数 T,代表测试数据组数(1≤T≤20),接下来 T 组测试数据。 每组测试数据占若干行,第一行一个正整数 N(1≤N≤1000),代表矩形的数量。接下来 N 行,每行 8 个整数x1,y1,x2,y2,x3,y3,x4,y4,代表

baidu_35522092的博客 802

什么是 WhatsApp云控 WhatsApp群发,WhatsApp协议,他们有什么区别?

下面我们sensws讲解下什么是WhatsApp云控 WhatsApp群发,WhatsApp协议

sendws的博客 3875

无源定位入门(二):FDOA(2)信号模型和原理

信号模型 假设地面固定目标信号源位置为 ,有M架飞机随机分布在空中,并作匀速直线运动。时刻t的时候第i架飞机的位置为,飞行速率为 , 假设目标的信号中心频率为 ,电磁波的传播速度为 ,则此时每个飞机接收目标信号的频率为 以第1架飞机为参考基站,目标信号到达第n架飞机和参考基站之间的FDOA 测量值可表示为 ...

syy_1797的博客 5956

BZOJ1185[HNOI2007] 最小矩形覆盖(旋转卡壳)

BZOJ1185[HNOI2007] 最小矩形覆盖 题面 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点的坐标 分析 首先可以先求凸包,因为覆盖了凸包上的顶点,凸包内的顶点也一定能被覆盖 结论:这个矩形的一条边一定与凸包的一条边重合。 然后对于凸包的每一条边\(\vec{s_is_{i+1}}\),我们通过旋转卡壳找到最左侧的点l,最右侧的点r,最高...

weixin_30551963的博客 201

SAP项目中 Waterfall vs Agile 的深度对比分析背景:方法论的演进SAP项目实施方法论经历了显著的代际更替。早期以 ASAP(Accelerated SAP) 为代表,采用经典瀑

本文对比分析了SAP项目实施中瀑布模型(ASAP)与敏捷方法(SAP Activate)的核心差异。瀑布模型采用线性流程,需求固定但变更成本高;敏捷方法则通过迭代开发实现动态调整,强调最佳实践和用户持续参与。文章指出,SAP系统的复杂性使纯粹敏捷难以实施,需在标准化与定制化间取得平衡。最终建议根据项目特性选择方法论:稳定需求适用瀑布模型,变化频繁则推荐敏捷,而SAP Activate本质上是两者的结构化融合,代表未来趋势。关键在于匹配项目实际需求,而非盲目追随方法论潮流。

金牌架构师 345

BZOJ 1185 HNOI2007 最小矩形覆盖 旋转卡壳

题目大意:最小矩形覆盖 首先有一个结论:凸包上一定有一条边与矩形的一条边重合 证明:如果不存在一条边与矩形的一条边重合,那么我将这个矩形旋转一下一定会比之前更小 于是我们枚举其中一条边,对其余三个点卡壳即可 这旋转卡壳写的真叫一个卡壳- - 还好1A掉了- - #include #include #include #include #include #define M 5050

世界 1861

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

BZOJ 1185 HNOI 2007 最小矩形覆盖 旋转卡壳

题目大意:给出平面上的一些点,问面积最小的矩形满足覆盖所有的点。 思路:覆盖问题和不是凸包上的点没关系,先做凸包。根据贪心的思想,这个覆盖了所有点的矩形肯定至少有一条边与凸包上的边重合,那么我们枚举凸包上的每一条边,对于这个已经确定了一条边的矩形,不难确定其他三个边。注意到已知当前直线的向量,就可以求出两侧和对面的向量,而这三个向量随着枚举的边的移动是单调的,所以就可以用旋转卡壳来卡住剩

(╯°口°)╯(┴—┴ 1039

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

bzoj 1185: [HNOI2007]最小矩形覆盖 旋转卡壳

先求出凸包,显然至少需要有一条边在凸包上(我只会感性理解不会证明QAQ),那么旋转卡壳一下就好了。 AC代码如下: #include #include #include #include #include #define eps 1e-12 #define N 50005 using namespace std; struct point{ double x,y; }a[N],q[N],t[

lych的博客 897

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

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

[HNOI2007][BZOJ1185] 最小矩形覆盖 [凸包+旋转卡壳]

题面 BZOJ题面 前置芝士 建议先学习向量相关的计算几何基础 计算几何基础戳这里 思路 用这道题学习一下凸包和旋转卡壳 首先是凸包部分 凸包 求凸包用的算法是graham算法 算法流程如下: 找到$y$坐标最小的一点作为原点 对原点之外的所有点按照到原点的极角排序(这里因为选取了最靠下的,所以极角范围在$[0,\pi]$) 依次遍历所有排序后的点,加入一个单调栈中:每次判断(栈顶元素和...

178

BZOJ1185 HNOI2007 最小矩形覆盖 凸包、旋转卡壳

传送门 首先,肯定只有凸包上的点会限制这个矩形,所以建立凸包。 然后可以知道,矩形上一定有一条边与凸包上的边重合,否则可以转一下使得它重合,答案会更小。 于是沿着凸包枚举这一条边,通过旋转卡壳找到离这条边最远的点以及这个矩形两端的点,这五个点构成的矩形就是一个可能的答案了。 各种判断用向量叉积和点积 注意一下输出\(-0.0000\)的情况 #include<bits/stdc++.h&g...

weixin_30279315的博客 163

【bzoj1185】[HNOI2007]最小矩形覆盖 (旋转卡壳)

给你一些点,让你用最小的矩形覆盖这些点 首先有一个结论,矩形的一条边一定在凸包上!!! 枚举凸包上的边 用旋转卡壳在凸包上找矩形另外三点。。。 注意精度问题 1 #include<cstdio> 2 #include<cmath> 3 #include<ctime> 4 #include<cstring&g...

dddddd12345456的博客 137

洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)

题目链接: 洛谷 P3187 [HNOI2007]最小矩形覆盖 BZOJ 1185: [HNOI2007]最小矩形覆盖 Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, 输出所求矩形的面积和四个顶点坐标 Input 第一行为一个整数n(3<=n<=50000) 从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计数法 ...

G19850917的博客 311

BZOJ 1185 [HNOI2007]最小矩形覆盖:凸包 + 旋转卡壳

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 题意:   给出二维平面上的n个点,问你将所有点覆盖的最小矩形面积。 题解:   先找出凸包,然后旋转卡壳。   在旋转卡壳中有一个结论:最小覆盖矩形一定有一条边在凸包上。   所以先枚举矩形在凸包上的那条边(p[i],p[i+1]),然后利用单调性找出...

a1392136的博客 216

BZOJ 1185 [HNOI2007]最小矩形覆盖 旋转卡壳

BZOJ 1185 [HNOI2007]最小矩形覆盖 旋转卡壳

-Claude 2579

[BZOJ1185][HNOI2007]最小矩形覆盖-[凸包+旋转卡壳]

Description 传送门 Solution 感性理解一下,最小矩形一定是由一条边和凸包上的边重合的。 然后它就是模板题了。。然而真的好难调,小于大于动不动就打错。 Code #include<iostream> #include<cstdio> #include<cstring> #include<algorit...

diancao3075的博客 135

[BZOJ1185][HNOI2007]最小矩形覆盖(凸包+旋转卡壳)

题目描述传送门题解首先先求一个凸包,矩形一定是把这个凸包覆盖掉 猜想:最小矩形的某一边一定和凸包的某一边重合 那么如何来证明呢? 可以用反证法。假设最小矩形不过凸包上的任意一条边,那么凸包最多有4个顶点在矩形上,可分为3种情况 1、凸包有2个顶点在矩形上 假设旋转了外接矩形一个角度,使其与对角线a夹角为α\alpha,那么新的矩形(用虚线表示)面积S=a2sinαcosα=12a2si

zyf2000 968

【BZOJ1185】【HNOI2007】最小矩形覆盖(凸包+旋转卡壳)

传送门 求最小矩阵覆盖

Stargazer的博客 251
上一篇: [BZOJ3527][Zjoi2014]力(FFT)
下一篇: [BZOJ2131]免费的馅饼(DP+树状数组)
FromATP
博客等级 码龄10年 75粉丝 163原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值