<p>Given an array of points on the <strong>X-Y</strong> plane <code>points</code> where <code>points[i] = [x<sub>i</sub>, y<sub>i</sub>]</code>, return <em>the area of the largest triangle that can be formed by any three different points</em>. Answers within <code>10<sup>-5</sup></code> of the actual answer will be accepted.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://s3-lc-upload.s3.amazonaws.com/uploads/2018/04/04/1027.png" style="height: 369px; width: 450px;" />
<pre>
<strong>Input:</strong> points = [[0,0],[0,1],[1,0],[0,2],[2,0]]
<strong>Output:</strong> 2.00000
<strong>Explanation:</strong> The five points are shown in the above figure. The red triangle is the largest.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> points = [[1,0],[0,0],[0,1]]
<strong>Output:</strong> 0.50000
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>3 &lt;= points.length &lt;= 50</code></li>
	<li><code>-50 &lt;= x<sub>i</sub>, y<sub>i</sub> &lt;= 50</code></li>
	<li>All the given points are <strong>unique</strong>.</li>
</ul>

class Solution {
public:
    using Point = vector<int>;

    int cross(Point const& p0, Point const& p1, Point const &p2) {
        return (p1[0] - p0[0]) * (p2[1] - p0[1]) - (p1[1] - p0[1]) * (p2[0] - p0[0]);
    }

    double segmentLength(vector<int> const& p0,
                         vector<int> const& p1)
    {
        double x = p1[0] - p0[0], y = p1[1] - p0[1];
        return sqrt(x * x + y * y);
    }

    double triangleArea(vector<int> const& p0,
                        vector<int> const& p1,
                        vector<int> const& p2)
    {
        double a = segmentLength(p0, p1);
        double b = segmentLength(p1, p2);
        double c = segmentLength(p2, p0);
        double s = (a + b + c) / 2;
        return sqrt(s * (s - a) * (s - b) * (s - c));
    }

    vector<Point> FindConvexHull(vector<Point> P) {
        size_t n = P.size(), k = 0;
        if (n <= 3) {
            return P;
        }
        vector<Point> H(2*n);

        sort(P.begin(), P.end());

        for (size_t i = 0; i < n; ++i) {
            while (k >= 2 && cross(H[k-2], H[k-1], P[i]) <= 0) k--;
            H[k++] = P[i];
        }

        for (size_t i = n-1, t = k+1; i > 0; --i) {
            while (k >= t && cross(H[k-2], H[k-1], P[i-1]) <= 0) k--;
            H[k++] = P[i-1];
        }

        H.resize(k-1);
        return H;
    }

    double largestTriangleArea(vector<vector<int>>& points) {
        auto convexHull = FindConvexHull(points);

        size_t sz = convexHull.size();
        double am = 0;
        for (int i = 0; i < sz; ++i) {
            for (int j = i + 1; j < sz; ++j) {
                for (int k = j + 1; k < sz; ++k) {
                    double area = triangleArea(convexHull[i],
                                               convexHull[j],
                                               convexHull[k]);
                    if (area > am) {
                        am = area;
                    }
                }
            }
        }
        return am;
    }
};
10000