博客
关于我
poj 2187 Beauty Contest(凸包求解多节点的之间的最大距离)
阅读量:448 次
发布时间:2019-03-06

本文共 2684 字,大约阅读时间需要 8 分钟。

凸包计算与Andrew算法实现

代码解析与实现思路

本节将详细阐述一个用于计算多个平面点集凸包的C++程序实现。通过对代码进行分析,我们将理解Andrew算法的核心思想及其在实际应用中的实现细节。

1. 代码结构概述

程序的主要部分包括以下几个要素:

  • 数据结构定义:定义了一个Point结构体,用于存储点的坐标信息,并提供了一系列与点运算相关的静态成员函数。
  • 比较函数:用于对点集进行排序,确保点的处理顺序符合凸包计算的需求。
  • 主程序逻辑:读取输入数据,排序点集,调用凸包构造算法,并输出结果。
  • 2. Andrew算法概述

    Andrew算法是一种高效的凸包计算算法,主要思想如下:

  • 预处理:将所有点按照横坐标进行排序。如果横坐标相同,则按纵坐标排序。
  • 构造下凸包:从最左边的点开始,依次检查每个点是否在当前下凸包的边上。如果不在,则将该点加入下凸包。
  • 构造上凸包:类似下凸包的构造方法,但从最右边的点开始,确保所有点都被包含在上凸包中。
  • 结果合并:将下凸包和上凸包合并,得到完整的凸包。
  • 3. 凸包构造过程详解

    3.1 下凸包构造

  • 排序:首先对所有点按照横坐标排序。如果横坐标相同,则按纵坐标排序。
  • 遍历处理:从最左边的点开始,依次处理每个点。
  • 叉积判断:对于当前点,检查它是否在当前下凸包的边上。如果叉积结果小于等于零,则说明该点位于边上或内部,需进一步处理。
  • 加入凸包:如果点不在当前下凸包边上,则将其加入下凸包。
  • 3.2 上凸包构造

  • 从右到左遍历:从最右边的点开始,依次处理每个点。
  • 叉积判断:同样使用叉积判断方法,检查点是否在上凸包边上或内部。
  • 构造上凸包:将不在上凸包边上的点加入上凸包。
  • 3.3 结果合并

    下凸包和上凸包合并后即为完整的凸包。需要注意的是,最后一个点会被重复计算,因此需要去重处理。

    4. 代码实现细节

    4.1 数据结构定义

    struct Point {    Point() {}    Point(int x, int y) {        this->x = x;        this->y = y;    }    int x, y;    static int cross(Point a, Point b) {        return a.x * b.y - a.y * b.x;    }    static int dist(Point a, Point b) {        return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);    }    Point operator-(Point tmp) {        return Point(x - tmp.x, y - tmp.y);    }};

    4.2 比较函数

    bool cmp(Point a, Point b) {    if (a.x == b.x)        return a.y < b.y;    return a.x < b.x;}

    4.3 主程序逻辑

    #include 
    #include
    #include
    #include
    using namespace std;Point operator-(Point tmp) { return Point(x - tmp.x, y - tmp.y);}int main() { int n; while (scanf("%d", &n) != EOF) { Point p[n]; for (int i = 0; i < n; ++i) { scanf("%d%d", &p[i].x, &p[i].y); } sort(p, p + n, cmp); int m = 0; for (int i = 0; i < n; ++i) { while (m > 0 && Point::cross(p[m-1] - p[m-2], p[i] - p[m-2]) <= 0) m--; ch[m++] = i; } int k = m; for (int i = n-2; i >= 0; --i) { while (m > k && Point::cross(p[m-1] - p[m-2], p[i] - p[m-2]) <= 0) m--; ch[m++] = i; } --m; int maxD = -1, j, d; for (int i = 0; i < m; ++i) { for (int j = 0; j < m; ++j) { if (j == i) continue; d = Point::dist(p[ch[i]], p[ch[j]]); if (d > maxD) { maxD = d; int x = ch[i]; int y = ch[j]; } } } printf("凸包边界点:"); for (int i = 0; i < m; ++i) { printf("%d ", ch[i]); } printf("\n最大距离:%d\n", maxD); }}

    5. 总结

    通过上述方法,我们成功实现了一个用于计算平面点集凸包的高效算法。Andrew算法凭借其线性时间复杂度和对内存的较低要求,在实际应用中具有重要的地位。这段代码不仅展示了算法的理论实现,还通过实际操作验证了其正确性。

    转载地址:http://orhuz.baihongyu.com/

    你可能感兴趣的文章
    Python 多处理如何优雅地退出?
    查看>>
    Python 多处理将子进程的标准输出重定向到 Tkinter 文本
    查看>>
    Python 多处理库错误(AttributeError:__exit__)
    查看>>
    Python 多处理模块的 .join() 方法到底在做什么?
    查看>>
    python 多线程与GIL
    查看>>
    Python 多线程学习(转)
    查看>>
    python 多进程-基础
    查看>>
    python 多进程-进阶-进程池
    查看>>
    python 多进程-进阶-进程间通信之Pipe
    查看>>
    python 多进程-进阶-进程间通信之Queue
    查看>>
    Python编程快速入门
    查看>>
    Python编程基础(附Pycharm与开发环境)
    查看>>
    python 如何“否定“value : 如果为真则返回假,如果为假则返回真
    查看>>
    Python 如何在 Web 环境中使用 Matplotlib 进行数据可视化
    查看>>
    python 如何把字符串转换成浮点数
    查看>>
    python 如果文件夹不存在就创建文件夹
    查看>>
    Python 如果有很多或以收缩形式
    查看>>
    Python 子进程 Popen 与 Pyinstaller
    查看>>
    Python 子进程 Popen.communicate() 等价于 Popen.stdout.read()?
    查看>>
    Python 子进程 Popen:为什么会出现“ls *.txt“?不行?
    查看>>