旋转卡壳,三种实现方式。

上述中说的三种是方式分别是

  1. kuangbin的-容易理解
  2. 挑战书上的-容易实现
  3. 我的-我的理解

第一种kuangbin板子

class Point
{
public:
    double x,y;
    Point() {}
    Point(double x,double y):x(x),y(y)
    {
    }
    Point operator+ (Point p)
    {
        return Point(add(x,p.x),add(y,p.y));
    }
    Point operator -(Point p)
    {
        return Point(add(x,-p.x),add(y,-p.y));
    }
    Point operator *(double d)
    {
        return Point(x*d,y*d);
    }
    double operator *(Point p)
    {
        return add(x*p.x,y*p.y);//外积
    }
    double operator ^(Point p) //内积
    {
        return add(x*p.y,-y*p.x);
    }
    double det(Point p)
    {
        return add(x*p.y,-y*p.x);
    }
    double len()
    {
        return sqrt(add(x*x,y*y));
    }
};
}
//旋转卡壳,求两点间距离平方的最大值
int rotating_calipers(Point p[],int n)//要求p序列为凸包序列
{
    int ans = 0;
    Point v;
    int cur = 1;
    for(int i = 0; i < n; i++)
    {
        v = p[i]-p[(i+1)%n];
        while((v^(p[(cur+1)%n]-p[cur])) < 0)             cur = (cur+1)%n;
        ans = max(ans,max(dist2(p[i],p[cur]),dist2(p[(i+1)%n],p[(cur+1)%n])));
    }
    return ans;
}

第二种挑战书上的-,不过我现在还是不是非常理解。

double add(double a,double b){//考虑误差的加法运算
    if(abs(a+b)<EPS*(abs(a)+abs(b))) return  0;
    return a+b;
}
class Point{
public:
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){
    }
    Point operator+ (Point p){
        return Point(add(x,p.x),add(y,p.y));
    }
    Point operator -(Point p){
        return Point(add(x,-p.x),add(y,-p.y));
    }
    Point operator *(double d){
        return Point(x*d,y*d);
    }
    double operator *(Point p){
        return add(x*p.x,y*p.y);//外积
    }
    double operator ^(Point p){//内积
        return add(x*p.y,-y*p.x);
    }
    double det(Point p){
     return add(x*p.y,-y*p.x);
    }
    double len(){
        return sqrt(add(x*x,y*y));
    }
};
double dist(Point p1,Point p2)//距离的平方
{
    return add((p1.x-p2.x)*(p1.x-p2.x),(p1.y-p2.y)*(p1.y-p2.y));
}
//旋转卡壳求平面最远点对
//输入: 多边形和顶点个数
//输出: 最远点对距离的平方
//时间复杂度n*logn(求凸包)+n(旋转卡壳)
double rotaing_calipers(P* ps,int pn)
{
    vector<P> qs = convex_hull(ps,pn);//求凸包
    int n=qs.size();
    if(n==2){
        return  dist(qs[0], qs[1]);
    }
    int i=0,j=0;//某个方向的对踵点对
    //求出x轴方向的对踵点对
    for(int k=0;k<n; k++){
        if(!cmp_x(qs[i],qs[k])) i=k;
        if(cmp_x(qs[j],qs[k])) j=k;
    }
    double res=0.0;
    int si=i,sj=j;
    while(i!=sj || j!= si){//将方向逐步旋转180度
        res=max(res,dist(qs[i],qs[j]) );
        // 判断先转到边i -(i+1)的发现方向还是 边j - j+1的法线方向
        if( (qs[(i+1)%n] - qs[i]).det(qs[(j+1)%n] - qs[j] ) < 0 ){ // i,i+1边的法线点是 j
            i=(i+1)%n;//先转到i - (i+1)的法线方向
        }
        else{
            j=(j+1)%n;//先转到j - (j+1)的法线方向
        }
    }
    return res;
}

第三种 根据自己理解写出的,旋转卡壳求出每个边对应的对踵点,更新点对最大距离。

double rotaing_calipers(P* ps,int pn)// 保证输入的已经是凸包且按顺序给出点
    vector<P> qs(ps,ps+pn);
    int n=qs.size();
    if(n==2){
        return  dist(qs[0], qs[1]);
    }
    int j=1;
    double ans=0.0;
    for(int i=0;i<n;++i)
    {
        while( (qs[(i+1)%n]-qs[i]).det( qs[(j+1)%n] - qs[j]) >=0 ) j=(j+1)%n;//找到i-i+1边对应的对踵点j
        ans=max(ans, max(dist(qs[j],qs[i]), dist(qs[j],qs[(i+1)%n] )) );
    }
    return ans;
}

 

全部评论

相关推荐

2024-12-29 11:08
湖南工业大学 Java
程序员牛肉:简历没什么大问题了。 而且不要再换项目了。三月份就开暑期实习了,现在都一月份了。实在来不及重新开一下项目了。把一个项目写完或许很快,但是把一个项目搞懂吃透并不简单。所以不要换项目了,把你简历上面的两个项目好好挖一挖吧。 具体 体现在:你能不能流利的说出你的项目的每一个功能点代码实现?你能不能说出在这块除了A技术之外,还有其他技术能够实现嘛?如果有其他技术能够实现,那你这块为什么选择了你当前用的这个技术?
投递牛客等公司
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务