【墨鳌】【凸包算法:Andrew算法 & Graham算法】

解题思路

  • 思路显而易见,计算几何求凸包
  • Orz大佬,这Python代码绝绝子 @z1m

补充

  • 2022/4/23 补充Graham算法

Andrew算法

C++版本

class Solution {
public:
    vector<vector<int>> outerTrees(vector<vector<int>>& trees) {
        auto cross=[](vector<int>&a,vector<int>&b,vector<int>&c){
            return (b[0]-a[0])*(c[1]-b[1])-(b[1]-a[1])*(c[0]-b[0]);
        };
        int n=trees.size();
        if(n<3)return trees;
        sort(begin(trees),end(trees),[](auto&a,auto&b){
            return make_pair(a[0],a[1])<make_pair(b[0],b[1]);
        });
        vector<vector<int>>low;
        for(auto&p:trees){
            while(low.size()>1 && cross(low[low.size()-1],low[low.size()-2],p)<0)low.pop_back();
            low.push_back(p);
        }
        reverse(begin(trees),end(trees));
        vector<vector<int>>top;
        for(auto&p:trees){
            while(top.size()>1 && cross(top[top.size()-1],top[top.size()-2],p)<0)top.pop_back();
            top.push_back(p);
        }
        set<pair<int,int>>s;
        for(auto&p:low)s.insert(make_pair(p[0],p[1]));
        for(auto&p:top)s.insert(make_pair(p[0],p[1]));
        vector<vector<int>>ans;
        for(auto[x,y]:s)ans.push_back({x,y});
        return ans;
    }
};

Python版本

class Solution:
    def outerTrees(self, points: List[List[int]]) -> List[List[int]]:
        n = len(points)
        if n < 3: return points
        points.sort(key = lambda x:(x[0],x[1]))
        cross = lambda a,b,c:(b[0]-a[0])*(c[1]-b[1])-(b[1]-a[1])*(c[0]-b[0])        
        lower = []
        for p in points:
            while len(lower) > 1 and cross(lower[-2],lower[-1],p) < 0: lower.pop()
            lower.append((p[0],p[1]))        
        upper = []
        for p in reversed(points):
            while len(upper) > 1 and cross(upper[-2],upper[-1],p) < 0: upper.pop()
            upper.append((p[0],p[1]))            
        return list(set(lower[:-1] + upper[:-1]))
  • 不要被长度吓到了,前面全是计算几何的板子

Graham算法

//
// 有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
// Created by Mo-Ao on 2022/4/23.
//

#ifndef TESTDEMO_SOLUTION_H
#define TESTDEMO_SOLUTION_H

#include <bits/stdc++.h>

using namespace std;

typedef double db;
const db eps = 1e-7;
const db pi = acos(-1.0);

struct Point {
    db x, y;

    Point(db x, db y) : x(x), y(y) {}

    bool operator<(const Point &o) const { return x != o.x ? x < o.x : y < o.y; }

    Point operator-(const Point &o) const { return Point(x - o.x, y - o.y); }

    Point operator+(const Point &o) const { return Point(x + o.x, y + o.y); }

    db operator&(const Point &o) const { return x * o.y - y * o.x; }

    db length() const { return sqrt(x * x + y * y); }

    void print() const {
        printf("(%lf,%lf)\n", x, y);
    }
};

typedef Point Vector;

db length(Point A, Point B) {
    Vector AB = B - A;
    return AB.length();
}

struct Polygon {
    vector<Point> points;

    void push(db x, db y) {
        points.emplace_back(x, y);
    }

    void push(Point P) {
        points.push_back(P);
    }

    void polarAngleSort() {
        Point &O = points[0];
        for (auto &P: points)if (P < O) swap(O, P);
        sort(begin(points)+1, end(points), [&](auto &A, auto &B) {
            db x = (A - O) & (B - O);
            if (x > eps) return true;
            if (x < -eps) return false;
            return length(O, A) < length(O, B);
        });
    }

    Point getBack(int i) {
        return *(points.end() - i);
    }

    Point get(int i) {
        return *(points.begin() + i);
    }

    int size() {
        return points.size();
    }

    void print() {
        for (auto &point: points) {
            point.print();
        }
    }
};


void Graham(Polygon &R, Polygon &A) {
    A.push(R.points[0]);
    A.push(R.points[1]);
    int n = R.points.size();
    for (int i = 2; i < n; i++) {
        Point P = R.get(i);
        while (A.size() > 1 && (((A.getBack(2) - P) & (A.getBack(1) - P)) < -eps))
            A.points.pop_back();
        A.push(P);
    }
}

class Solution {
public:
    vector<vector<int>> outerTrees(vector<vector<int>> &trees) {

        if(trees.size()<=3)return trees;

        Polygon input, ans;
        for (auto &tree: trees)
            input.push(tree[0], tree[1]);
        input.polarAngleSort();

        input.print();
        //cout << "---" << endl;

        Graham(input, ans);
        vector<vector<int>> res;

        set<pair<int, int>> s;
        for (auto &point: ans.points) {
            res.push_back({(int) point.x, (int) point.y});
            s.insert(make_pair((int) point.x, (int) point.y));
        }
        reverse(input.points.begin(), input.points.end());

        Point A = ans.getBack(1);
        Point B = ans.get(0);
        for (auto &point: input.points) {
            auto P = make_pair((int) point.x, (int) point.y);
            if (s.count(P) == 0) {
                if (((A - point) & (B - point)) == 0) res.push_back({P.first, P.second});
            }
        }

        return res;
        //polygon.print();
        //convexHull.print();

    }
};

#endif //TESTDEMO_SOLUTION_H
posted @ 2022-04-23 13:02  墨鳌  阅读(110)  评论(0编辑  收藏  举报