hdu 6219

(Computational Geometry + DP)
meaning of the title: Total T(T<100) Set of test data, the test data of each plane containing the n(n<50) Coordinate points, find the largest area of ​​the convex hull of the space they thereof. (I.e., the package does not contain any internal projections other points)

Thinking: enumeration lower left corner point of the convex hull, and then find the maximum DP empty area of ​​the convex hull in this position can constitute a starting point of the last maximum value the vacant area of ​​the convex hull is the answer. DP process: Suppose the current point O To the lower left corner, dp[i][j] Representation was based on The i ij Is the maximum area of ​​the convex hull constituted by the last two sides of the convex hull. State transition equation: dp[i][j]=max(dp[i][j],triangthe e(O,i,j)+dp[j][k]) . time complexity: O ( n4)

Tucao: The key question is how good start in order to enumerate! Then, ah I know this question has O ( n3) Solution, but I do not. . (4 th but this solution can also run speed 233) write the code to pay particular attention to the point where the edge of the convex hull. Last point code entirely in int several times faster than all of them with a double running speed. Use double code ran 1216ms, use int code ran only 171ms.

Code:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define LL long long

using namespace std;
const int maxn = 60;

struct Point {
    int x, y;
    Point(const Point& rhs): x(rhs.x), y(rhs.y){ }
    Point(int x = 0, int y = 0): x(x), y(y) { }

    friend Point operator + (const Point& A, const Point& B) { return Point(A.x+B.x, A.y+B.y); }
    friend Point operator - (const Point& A, const Point& B) { return Point(A.x-B.x, A.y-B.y); }
    friend bool operator == (const Point& A, const Point& B) { return A.x==B.x && A.y==B.y; }
}P[maxn], Pcur[maxn];
typedef Point Vector;

int len2(Point A, Point B) { Point C = B-A; return (C.x*C.x + C.y*C.y); }
int Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
bool cmp1(const Point& A, const Point& B) {
    return A.y < B.y || (A.y == B.y && A.x < B.x);
}
bool cmp2(const Point& A, const Point& B) {
    int c = Cross(A, B);
    if(c == 0) return len2(A,Point(0,0)) < len2(B,Point(0,0));
    return c > 0;
}

struct Line {
    Point P;
    Vector v;
    Line() {}
    Line(const Point& P, const Vector& v): P(P), v(v) {}
};
bool OnLeft(Line L, Point p) {
    return Cross(L.v, p-L.P) > 0;
}
bool PointInTriangle(Point a, Point b, Point c, Point k) {
    Line lx(a, b-a), ly(b, c-b), lz(c, a-c);
    return OnLeft(lx, k) && OnLeft(ly, k) && OnLeft(lz, k);
}

int dp[maxn][maxn];

int do_DP(int n) {
    for(int i=0; i<n; i++) // initialize
        for(int j=0; j<n; j++)
            dp[i][j] = -1;
    int ret = -1;  // work
    for(int i=1; i<n; i++)
        for(int j=1; j<i; j++) if(Cross(Pcur[i], Pcur[j]) != 0) {
            bool triangle = 1; // see if 0,i,j can form a triangle
            for(int k=j+1; k<i; k++)
                if(PointInTriangle(Pcur[0], Pcur[j], Pcur[i], Pcur[k])) {
                    triangle = 0; break ;
                }
            if(!triangle) continue ;
            int tri_area = abs(Cross(Pcur[i]-Pcur[0], Pcur[j]-Pcur[0]));
            dp[i][j] = tri_area; // start DP
            if(Cross(Pcur[j], Pcur[j-1]) != 0) {
                for(int k=1; k<j; k++)
                    if(dp[j][k] > 0 && OnLeft(Line(Pcur[k], Pcur[j]-Pcur[k]), Pcur[i])) {
                        dp[i][j] = max(dp[i][j], tri_area+dp[j][k]);
                    }
            }
            ret = max(dp[i][j], ret);
        }
    return ret;
};

int solve(int n) {
    sort(P, P+n, cmp1);
    int ret = 0;
    for(int i=0; i<n-2; i++) { // choose the lower left point for convex hull
        for(int j=0; j+i<n; j++)
            Pcur[j] = P[j+i] - P[i];
        sort(Pcur+1, Pcur+n-i, cmp2);
        ret = max(ret, do_DP(n-i));
    }
    return ret;
}

int main() {
    //freopen("in.txt","r",stdin);
    int T, n;
    scanf("%d",&T);
    while(T --) {
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%d%d",&P[i].x,&P[i].y);
        double ans = (double)solve(n)/2.0;
        printf("%.1f\n",ans);
    }
    return 0;
}
Published 40 original articles · won praise 44 · views 90000 +

Guess you like

Origin blog.csdn.net/Site1997/article/details/78786805