旋转卡壳部分模板

凸包直径

旋转卡壳凸包直径详解

//计算凸包直径,输入凸包ch,顶点个数为n,按逆时针排列,输出直径的平方

int rotating_calipers(int n)
{
    int q = 1;
    int ans = 0;
    ch[n] = ch[0];
    for(int i = 0 ; i < n;  i++)
    {
        while(mul(ch[i+1],ch[q+1],ch[i])>mul(ch[i+1],ch[q],ch[i]))//枚举凸包一条边并扫描其它点,通过计算三角形面积的方法找到最远的点
        q = (q+1)%n;
        ans = max(ans,max(dis(ch[i]-ch[q]),dis(ch[i+1]-ch[q+1])));
    }
    return ans;
}
 

凸包间最小距离

struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y) {} //构造函数 方便代码编写
}p[N],q[N];
typedef Point pointt;
pointt operator + (Point a,Point b)
{
    return Point(a.x+b.x,a.y+b.y);
}
pointt operator - (Point a,Point b)
{
    return Point(a.x-b.x,a.y-b.y);
}
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
bool operator == (const Point &a,const Point &b)
{
    return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double dot(Point a,Point b)
{
    return a.x*b.x+a.y*b.y;
}
double  dis(Point a)
{
    return sqrt(dot(a,a));
}
double cross(Point a,Point b)
{
    return a.x*b.y-a.y*b.x;
}
void anticlock(Point p[],int n)//逆时针排序
{
    for(int i = 0 ; i < n-2 ; i++)
    {
        double k = cross(p[i+1]-p[0],p[i+2]-p[0]);
        if(dcmp(k)>0) return ;
        else if(dcmp(k)<0)
        {
            reverse(p,p+n);
            return ;
        }
    }
}
double distoline(Point a,Point b,Point c)//点到线段ab的最短距离
{
    if(dcmp(dis(a-b))==0) return dis(a-c);
    if(dcmp(dot(a-b,a-c))<0) return dis(a-c);
    if(dcmp(dot(b-a,b-c))<0) return dis(b-c);
    return fabs(cross(a-b,a-c))/dis(a-b);
}
double dist(Point a,Point b,Point c,Point d)//线段ab和cd间的最短距离
{
    double ans = distoline(a,b,c);
    ans = min(ans,distoline(a,b,d));
    ans = min(ans,distoline(c,d,a));
    ans = min(ans,distoline(c,d,b));
    return ans;
}
double mul(Point a,Point b,Point c)
{
    return cross(b-a,c-a);
}
double  solve(Point p[],int n,Point q[],int m)
{
    int i;
    int miny = 0,maxy = 0;
    for(i = 0;i < n; i++)
    {
        if(p[i].y<p[miny].y)
        miny = i;
    }
    for(i =0 ; i< m ; i++)
    if(q[i].y>q[maxy].y) maxy = i;
    double ans = dis(p[miny]-q[maxy]);
    for(i = 0 ;i < n; i++)
    {
        double tmp;
        while(tmp = mul(p[miny],p[miny+1],q[maxy+1])-mul(p[miny],p[miny+1],q[maxy])>eps)
        maxy = (maxy+1)%m;
        if(dcmp(tmp)>0) ans = min(ans,distoline(p[miny],p[miny+1],q[maxy]));
        else
        ans = min(ans,dist(p[miny],p[miny+1],q[maxy],q[maxy+1]));//边-边
        miny = (miny+1)%n;
    }
    return ans;
}

旋转卡壳部分模板

时间: 2024-10-13 11:12:29

旋转卡壳部分模板的相关文章

模板 凸包 旋转卡壳

模板  凸包  旋转卡壳 lrj <训练指南> P272 对于个点按照 x 从小到大排序,再按照 y 点从小到大排序,删除重复的点后,得到序列 p0,p1,p2..., 把 p0 和 p1 放入凸包. 从p2开始,当新点在凸包“前进”方向的左边时继续,否则依次删除最近加入凸包的点,直到新点在左边 PS:判断用叉积即可 1 /******************************************** 2 计算凸包,输入点数组 p, 个数为 n , 输出点数组 ch. 函数返回凸包顶

模板 旋转卡壳 凸包

模板 旋转卡壳 凸包 好早以前看的,现在再记下来吧,当做复习一遍. 那么,先提一下最基本最暴力的求凸包直径的方法吧---枚举...好吧..很多问题都可以用 枚举 这个“万能”的方法来解决,过程很简单方便是肯定的,不过在效率上就要差很远了.  要求一个点集的直径,即使先计算出这个点集的凸包,然后再枚举凸包上的点对,这样来求点集直径的话依然会在凸包上点的数量达到O(n)级别是极大的降低它的效率,也浪费了凸包的优美性质.不过在数据量较小或者很适合时,何必要大费周折的用那些麻烦复杂的算法呢,枚举依然是解

[模板] 计算几何2: 自适应Simpson/凸包/半平面交/旋转卡壳/闵可夫斯基和

//to update 一些基本的定义在这里: [模板] 计算几何1(基础): 点/向量/线/圆/多边形/其他运算 自适应Simpson 凸包 Andrew 算法, 即分别求上, 下凸包. 时间复杂度 \(O(n \log n)\). struct tvec{db x,y;}; il int dcmp(db a){return fabs(a)<=eps?0:(a>0?1:-1);} il db p2(db a){return a*a;} il db gougu1(db a,db b){retu

【模板】 旋转卡壳 poj2187

题目链接:https://vjudge.net/problem/POJ-2187 旋转卡壳模板题.参考了hzwer(http://hzwer.com/4224.html) 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #define eps 1e-8 6 using namespace std; 7 int n,top; 8 const in

【模板】旋转卡壳求 面积最大的三角形 poj2079

题目链接:https://vjudge.net/problem/POJ-2079 graham跑的巨慢,Andrew跑的巨快.还好写. 有两种写法. 旋转卡壳枚举三个点的(94ms) 1 /************************************************************************* 2 > File Name: poj2079.cpp 3 # File Name: poj2079.cpp 4 # Author : xiaobuxie 5 #

NYOJ_253:LK的旅行(旋转卡壳入门)

题目链接 求平面最大点对. 找凸包 -> 根据凸包运用旋转卡壳算法求最大点对(套用kuang巨模板) 关于旋转卡壳算法 #include<bits/stdc++.h> using namespace std; struct point { int x,y; point operator -(const point& rhs)const { point ret; ret.x=x-rhs.x; ret.y=y-rhs.y; return ret; } int operator *(c

【最小矩形面积覆盖:凸包+旋转卡壳】UVA 10173 Smallest Bounding Rectangle

[最小矩形面积覆盖:凸包+旋转卡壳]UVA 10173 Smallest Bounding Rectangle 题目链接:UVA 10173 Smallest Bounding Rectangle 题目大意 给你n个点,求能够覆盖所有点集的最小矩形面积. 笔者的第2道凸包题目,凸包 + 旋转卡壳,实现点集的最小矩形面积覆盖问题 ">=0"写成"<=0"坑了我一下午!QAQ 说一下思路 ①Graham's Scan法构建凸包,时间复杂度O(nlogn) ②

【旋转卡壳】poj3608 Bridge Across Islands

给你俩凸包,问你它们的最短距离. 咋做就不讲了,经典题,网上一片题解. 把凸包上的点逆时针排序.可以取它们的平均点,然后作极角排序. 旋转卡壳其实是个很模板化的东西-- 先初始化分别在凸包P和Q上取哪个点,一般在P上取纵坐标最小的点,在Q上取纵坐标最大的点 for i=1 to n(n是凸包P上的点数) { while(两条边的叉积>0) { 凸包Q上的点++ } 计算当前两条边之间的答案(或者说每条边的2个端点到另一条边的答案) 凸包P上的点++ } #include<cstdio>

算法复习——凸包加旋转卡壳(poj2187)

题目: Description Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, earning the title 'Miss Cow World'. As a result, Bessie will make a tour of N (2 <= N <= 50,000) farms around the world in order to spread goodwill