HDU 2202 最大三角形 (凸包+旋转卡壳)

来源:互联网 发布:jq遍历json数组 radio 编辑:程序博客网 时间:2024/05/21 06:30

题目大意

  • 给出n(3 <= n <= 50000)个点,求这n个中最大三角形的面积

分析

  • 暴力求解O(n^3),妥妥超时
  • 很容易想明白,最大三角形必定存在在这n个点构成的最大严格凸包中。所以先求凸包,时间复杂度O(nlogn)
  • 然后用旋转卡壳法在这个凸包中求最大三角形面积。时间复杂度O(m^2)(m为凸包中的点的数量)

代码

#include <iostream>#include <algorithm>#include <iomanip>using namespace std;const int maxn = 50010;struct Point {    int x , y;    bool operator < (Point const &rhs) const {        return (x < rhs.x) || (x == rhs.x && y < rhs.y);    }};int Cross(Point const &O , Point const &A , Point const &B){    int xoa = A.x - O.x;    int xob = B.x - O.x;    int yoa = A.y - O.y;    int yob = B.y - O.y;    return xoa * yob - xob * yoa;}int Andrew(Point *p , int n , Point *ch){    sort(p , p + n);    int m = 0;    for(int i = 0; i < n; i++) { //下凸包        while(m > 1 && Cross(ch[m-2] , ch[m-1] , p[i]) < 0) m--;        ch[m++] = p[i];    }    int k = m;    for(int i = n - 2; i >= 0; i--) {  //上凸包        while(m > k && Cross(ch[m-2] , ch[m-1] , p[i]) < 0) m--;        ch[m++] = p[i];    }    if(n > 1) m--;    return m;}Point p[maxn] , ch[maxn];int main(){    int n;    while(cin >> n)    {        for(int i = 0; i < n; i++) cin >> p[i].x >> p[i].y;        int m = Andrew(p , n , ch); //求凸包        //旋转卡壳法        int ans = 0;        for(int i = 0; i < m; i++) {            int q = 1;            for(int j = i + 1; j < m; j++) {                while(Cross(ch[i],ch[j],ch[q+1]) > Cross(ch[i],ch[j],ch[q]))                    q = (q + 1) % m;                ans = max(ans , Cross(ch[i],ch[j],ch[q]));            }        }        cout << fixed << setprecision(2) << ans / 2.0 << endl;    }    return 0;}
0 0
原创粉丝点击