HDU 6219

(計算幾何学+ DP)
のタイトルの意味:合計 TT< 100 テストデータのセットを含む各平面の試験データ N N < 50 座標点を、スペースその彼らの凸包の最大面積を見つけます。(すなわち、パッケージは、任意の内部突起他の点が含まれていません)

思考:列挙凸船体の左下隅のポイントして、[凸包の空き領域が答えである最後の最大値の開始点を構成することができ、この位置で凸包の最大DP空の領域を見つけます。DPプロセス:現在のポイントを仮定 ザ・ 左下隅に、 DP [ I ] [ J ] 表現はに基づいていました I J 凸包の最大面積は、凸包の最後の二つの側面で構成されています。状態遷移方程式: DP [ I ] [ J ] = M X DP [ I ] [ J ] tはrはI n個のGEO I J + DP [ J ] [ K ] 時間計算: O N4

Tucao:重要な問題は、列挙するために、どのように良いスタートです!続いて、ああ、私はこの質問を持って知っています O N3 ソリューションが、私にはありません。(4番目が、この解決策も実行できる速度233)ここで、凸包のエッジ点に特に注意を払うためにコードを書きます。速くダブル走行速度とそれらのすべてよりも完全にint型の数倍の最後のポイントコード。ダブルコードのRAN 1216msを使用し、使用のint型のコードは171ms走りました。

コード:

#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;
}
公開された40元の記事 ウォン称賛44 ビュー90000 +

おすすめ

転載: blog.csdn.net/Site1997/article/details/78786805