前言

旋转卡壳(Rotating Calipers)可以在凸包上维护许多有用的信息,最常见的就是凸包直径(平面最远点对)。

注意:本文不介绍所谓的 “人类智慧” 乱搞做法。

算法流程

首先我们需要求出点集的凸包(我个人喜欢 Andrew 算法)。

然后我们考虑选定凸包的一条边所在的直线,比如 \(AB\)。然后找到凸包的所有顶点中离它最远的点,在这个例子中是 \(D\)。然后凸包直径就 可能 是 \(AD\) 或 \(BD\)。

然后我们继续。逆时针选择下一条边 \(AE\),这时我们发现最远点变成了 \(C\),然后尝试用 \(AC,EC\) 更新答案。以此类推。这样我们就找到了凸包直径。

但是这样子时间复杂度是 \(O(n^2)\) 的,应该无法通过。

但是根据以前的经验,似乎最远点也是逆时针旋转的。换句话说,逆时针遍历的点到直线的距离单调。

这也可以用凸包的凸性来解释。我无法给出详细证明,但是大家不妨手动画几个图,就可以感性的理解了。

于是我们就可以用一个漂亮的双指针解决了。

P145 【模板】旋转卡壳 代码

注意本题需要输出凸包直径的平方。

#include <bits/stdc++.h>
#define int long long
using namespace std; int n; const double eps=1e-9;
int dcmp(double x){
return (fabs(x)<=eps)?0:(x<0?-1:1);
}
struct Point{
double x,y;
Point(double X=0,double Y=0){x=X,y=Y;}
};
struct Vector{
double x,y;
Vector(double X=0,double Y=0){x=X,y=Y;}
};
inline Vector operator-(Point x,Point y){// 点-点=向量
return Vector(x.x-y.x,x.y-y.y);
}
inline double cross(Vector x,Vector y){ // 向量叉积
return x.x*y.y-x.y*y.x;
}
inline double operator*(Vector x,Vector y){ // 向量叉积
return cross(x,y);
}
inline double len(Vector x){ // 向量模长
return sqrt(x.x*x.x+x.y*x.y);
} int stk[50005];
bool used[50005];
vector<Point> ConvexHull(Point* poly, int n){ // Andrew算法求凸包
int top=0;
sort(poly+1,poly+n+1,[&](Point x,Point y){
return (x.x==y.x)?(x.y<y.y):(x.x<y.x);
});
stk[++top]=1;
for(int i=2;i<=n;i++){
while(top>1&&dcmp((poly[stk[top]]-poly[stk[top-1]])*(poly[i]-poly[stk[top]]))<=0){
used[stk[top--]]=0;
}
used[i]=1;
stk[++top]=i;
}
int tmp=top;
for(int i=n-1;i;i--){
if(used[i]) continue;
while(top>tmp&&dcmp((poly[stk[top]]-poly[stk[top-1]])*(poly[i]-poly[stk[top]]))<=0){
used[stk[top--]]=0;
}
used[i]=1;
stk[++top]=i;
}
vector<Point> a;
for(int i=1;i<=top;i++){
a.push_back(poly[stk[i]]);
}
return a;
} struct Line{
Point x;Vector y;
Line(Point X,Vector Y){x=X,y=Y;}
Line(Point X,Point Y){x=X,y=Y-X;}
}; inline double DistanceToLine(Point P,Line x){// 点到直线的距离
Vector v1=x.y, v2=P-x.x;
return fabs(cross(v1,v2))/len(v1);
} double RoatingCalipers(vector<Point> poly){// 旋转卡壳
if(poly.size()==3) return len(poly[1]-poly[0]);
int cur=0;
double ans=0;
for(int i=0;i<poly.size()-1;i++){
Line line(poly[i],poly[i+1]);
while(DistanceToLine(poly[cur], line) <= DistanceToLine(poly[(cur+1)%poly.size()], line)){
cur=(cur+1)%poly.size();
}
ans=max(ans, max(len(poly[i]-poly[cur]), len(poly[i+1]-poly[cur])));
}
return ans;
} Point poly[50005]; signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>poly[i].x>>poly[i].y;
double v=RoatingCalipers(ConvexHull(poly, n));
cout<<(int)(v*v);
return 0;
}

旋转卡壳(求凸包直径)学习笔记 | 题解 P1452 [USACO03FALL]Beauty Contest G /【模板】旋转卡壳的更多相关文章

  1. luogu P1452 [USACO03FALL]Beauty Contest G /【模板】旋转卡壳

    LINK:旋转卡壳 如题 是一道模板题. 容易想到n^2暴力 当然也能随机化选点 (还真有人过了 考虑旋转卡壳 其实就是对于某个点来说找到其最远的点. 在找的过程中需要借助一下个点的帮助 利用当前点到 ...

  2. UVa 1453 - Squares 旋转卡壳求凸包直径

    旋转卡壳求凸包直径. 参考:http://www.cppblog.com/staryjy/archive/2010/09/25/101412.html #include <cstdio> ...

  3. POJ 2187 Beauty Contest【旋转卡壳求凸包直径】

    链接: http://poj.org/problem?id=2187 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22013#probl ...

  4. poj 2187 Beauty Contest , 旋转卡壳求凸包的直径的平方

    旋转卡壳求凸包的直径的平方 板子题 #include<cstdio> #include<vector> #include<cmath> #include<al ...

  5. Yii框架学习笔记(二)将html前端模板整合到框架中

    选择Yii 2.0版本框架的7个理由 http://blog.chedushi.com/archives/8988 刚接触Yii谈一下对Yii框架的看法和感受 http://bbs.csdn.net/ ...

  6. bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包

    [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 2081  Solved: 920 ...

  7. 位运算求最值 学习笔记 (待补充QAQ)

    没有什么前言?直接进入正题qwq 俩俩异或 求最值: 建trie树 O(n)枚举每个数找这个数的最值,每次反走就成,还可以剪枝一波(如果在某位已经小于ans显然可以直接return? void Ins ...

  8. Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离

    \(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接 ...

  9. 【洛谷 P1452】 Beauty Contest (二维凸包,旋转卡壳)

    题目链接 旋转卡壳模板题把. 有时间再补总结吧. #include <cstdio> #include <cmath> #include <algorithm> u ...

  10. DirectX11 学习笔记2 - 加入关键事件 实现视角转换 旋转

    上的程序的的基础上.在基类D3DBase添加摄像头功能 //录影机 void D3DBase::setCamera() { //关键事件 //假定A,S,D,W,Q,E,Z,X,C键被按下.动摄像机 ...

随机推荐

  1. Redis5种数据类型

    字符串 @GetMapping("/string") public String stringTest(){ redisTemplate.opsForValue().set(&qu ...

  2. element-ui v-table 复选框默认选中

    <el-table ref="refTable" :data="list" v-loading="listLoading" eleme ...

  3. pinpoint部署

    pinpoint是一个分析大型分布式系统的平台,提供解决方案来处理海量跟踪数据,主要面向基于tomcat的Java 应用. pinpoint使用HBASE储存数据. 下面介绍pinpoint部署及应用 ...

  4. prefetch和preload

    前面的话 基于VUE的前端小站改造成SSR服务器端渲染后,HTML文档会自动使用preload和prefetch来预加载所需资源,本文将详细介绍preload和prefetch的使用 资源优先级 在介 ...

  5. Ant Design Pro:Layout 组件——嵌套布局

    在   BasicLayout.jsx   文件中修改 <ProLayout layout="topmenu" className="chenshuai2144&q ...

  6. 2022春每日一题:Day 33

    题目:[USACO 6.1.3] Cow XOR 没找到这题具体网址,这个题就是求最大异或区间(总长度尽量小,右端点尽量大) 嗯很显然一个[l,r]的异或和=s[r]s[l-1],那么现在有了优秀的n ...

  7. 面试 个人摸底监测 考察考察JS三座⼤⼭ 1. 原型和原型链 2. 作⽤域与闭包 3. 异步和单线程 (第四天)

    01.如何判断⼀个变量是不是数组? let arr = [1,2,3,4] function fun(){ return arr instanceof Array } 02.如何使⽤class实现继承 ...

  8. 线程(Thread)基本用法

    一.线程的调用 1.无参 def run_01(): for i in range(6, 10): print("test01", i) time.sleep(1) th_01 = ...

  9. Vscode连接gitee远程仓库

    Git初始化项目 1. Git的基础配置 Git的安装配置 下载地址为:http://git-scm.com/downloads 安装完第一步要做的是,设置你的用户名和邮件地址. git config ...

  10. 关于tomcat8在windows2008下高并发下有关问题的解决方案

    关于tomcat8在windows2008下高并发下问题的解决方案 因为客户服务器特殊的环境问题,只能使用windows2008r2服务器,然而配置过后,网站的高访问量很快就出现了各种问题,以下是解决 ...