找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 22|回复: 0

分治算法求解凸包问题

[复制链接]

0

主题

0

回帖

26

积分

管理员

积分
26
发表于 2024-10-6 10:42:01 | 显示全部楼层 |阅读模式
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <algorithm>
  5. using namespace std;
  6. // 定义点的结构体
  7. struct Point {
  8.     int x, y;
  9. };
  10. // 计算点P到直线AB的距离
  11. double distanceToLine(const Point& A, const Point& B, const Point& P) {
  12.     return abs((B.x - A.x) * (A.y - P.y) - (A.x - P.x) * (B.y - A.y)) /
  13.         sqrt(pow(B.x - A.x, 2) + pow(B.y - A.y, 2));
  14. }
  15. // 计算叉积,判断点C在向量AB的右侧、左侧或共线
  16. int crossProduct(const Point& A, const Point& B, const Point& C) {
  17.     return (B.x - A.x) * (C.y - B.y) - (B.y - A.y) * (C.x - B.x);
  18. }
  19. // 判断点C是否在向量AB的右侧
  20. bool isRightOf(const Point& A, const Point& B, const Point& C) {
  21.     return crossProduct(A, B, C) < 0;
  22. }
  23. // 快速凸包算法的部分实现
  24. vector<Point> quick_half_hull(vector<Point>& S, const Point& a, const Point& b) {
  25.     if (S.empty()) return {};
  26.     double maxDist = -1;
  27.     Point c;
  28.     for (const auto& point : S) {
  29.         double dist = distanceToLine(a, b, point);
  30.         if (dist > maxDist) {
  31.             maxDist = dist;
  32.             c = point;
  33.         }
  34.     }
  35.     vector<Point> A, B;
  36.     // 筛选出右侧的点集A和B
  37.     for (const auto& point : S) {
  38.         if (isRightOf(b, c, point)) {
  39.             A.push_back(point);
  40.         }
  41.         else if (isRightOf(c, a, point)) {
  42.             B.push_back(point);
  43.         }
  44.     }
  45.     vector<Point> QA = quick_half_hull(A, a, c);
  46.     vector<Point> QB = quick_half_hull(B, c, b);
  47.     vector<Point> result;
  48.     result.insert(result.end(), QA.begin(), QA.end());
  49.     result.push_back(c);
  50.     result.insert(result.end(), QB.begin(), QB.end());
  51.     return result;
  52. }
  53. vector<Point> quick_hull(vector<Point>& S) {
  54.     if (S.size() < 3) return S;
  55.     // 寻找极端点a和b
  56.     sort(S.begin(), S.end(), [](const Point& p1, const Point& p2) {
  57.         return (p1.x < p2.x) || (p1.x == p2.x && p1.y < p2.y);
  58.         });
  59.     Point a = S[0];
  60.     Point b = S[S.size() - 1];
  61.     vector<Point> A, B;
  62.     // 筛选出右侧的点集A和B
  63.     for (const auto& point : S) {
  64.         if (isRightOf(b, a, point)) {
  65.             A.push_back(point);
  66.         }
  67.         else if (isRightOf(a, b, point)) {
  68.             B.push_back(point);
  69.         }
  70.     }
  71.     vector<Point> QA = quick_half_hull(A, a, b);
  72.     vector<Point> QB = quick_half_hull(B, b, a);
  73.     vector<Point> result;
  74.     result.push_back(a);
  75.     result.insert(result.end(), QA.begin(), QA.end());
  76.     result.push_back(b);
  77.     result.insert(result.end(), QB.begin(), QB.end());
  78.     return result;
  79. }
  80. int main() {
  81.     // 示例点集
  82.     vector<Point> points = { {0, 0}, {4, 4}, {4, 0}, {0, 4}, {3, 3} ,{3,1},{2,1},{1,2},{3,2},{4,3},{2,4} ,{0,2},{0,5} };
  83.     // 调用凸包算法
  84.     vector<Point> result = quick_hull(points);
  85.     // 输出凸包顶点
  86.     cout << "Convex Hull Points:\n";
  87.     for (const auto& point : result) {
  88.         cout << "(" << point.x << ", " << point.y << ")\n";
  89.     }
  90.     return 0;
  91. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|膜结构网

GMT+8, 2024-12-27 06:49 , Processed in 0.146332 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表