• 凸包


    转载摘自大神博客:

    https://thewalker88.com/?p=84

    求组成凸包的点坐标,周长面积等问题

    针对这个问题:Melkman复杂度n,且可以在线处理,而Graham复杂度nlogn(因为必须先排序)
    平面上有一个简单多边形,沿着多边形的边,按照逆时针的顺序给出多边形的顶点的坐标,要求你求出此多边形的凸包。
    如果是一般散点集问题的话,那它跟Graham复杂度相同,均需要先排个序nlogn

    melkman算法想象成渔网网鱼就成,左右边同时包揽

    struct Vector
    {
    double x, y;
    };
    struct Point
    {
    double x, y;
    } p[N],dq[N];
    bool cmp(Point a, Point b)
    {
    if (a.y == b.y)
    return a.x < b.x;
    return a.y < b.y;
    }
    double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }//叉乘,右手螺旋,左上正右下负
    double side(Point a, Point b, Point p)//判断p在a->b直线那一侧
    {
    Vector A = (Vector){b.x - a.x, b.y - a.y};
    Vector B = (Vector){p.x - a.x, p.y - a.y};
    return Cross(A, B);
    }
    
    void Melkman(int n, int &head, int &tail)
    {
    sort(p + 1, p + 1 + n, cmp);//如果是处理一般点集问题,这里排序保证了这只“渔网”从西南角往东北角突击
    dq[head = n] = p[2];//这里直接丢1,2进来,3并不需要如网上说的手动调
    dq[tail = n + 1] = p[1];
    dq[++tail] = p[2];
    For(i, 3, n)
    {
    // if (side(dq[head + 1], dq[head], p[i])<0 && side(dq[tail - 1], dq[tail], p[i])>0)//如果是处理简单多边形的题要加这句话
    // continue;
    while (tail - head >= 2 && side(dq[head + 1], dq[head], p[i]) >= 0)//head+1->head从左路包揽敌人,如果有更左侧的鱼,那就调整角度向左扩张渔网
    ++head;
    dq[--head] = p[i];
    while (tail - head >= 2 && side(dq[tail - 1], dq[tail], p[i]) <= 0 )//tail-1->tail从右路包揽敌人
    --tail;
    dq[++tail] = p[i];
    }
    }
    For(i,head,tail-1)//因为head和tail存的值一定相同,输出点坐标输出一边就行
    cout<<dq[i].x<<" "<<dq[i].y<<endl;
  • 相关阅读:
    【使用 DOM】使用 DOM 元素
    【使用 DOM】使用 Window 对象
    【使用 DOM】使用 Document 对象
    Groovy中的脚本与类
    Groovy操作符
    Android开源天气预报应用Weather-Lite
    进击的RecyclerView入门三(要是能拖动就好了)
    进击的RecyclerView入门二(来点小装饰?)
    进击的RecyclerView入门一(简单上手)
    Android 5.0+删除Sdcard文件
  • 原文地址:https://www.cnblogs.com/planche/p/9426915.html
Copyright © 2020-2023  润新知