1. 程式人生 > >6219 Empty Convex Polygons——dp+幾何

6219 Empty Convex Polygons——dp+幾何

首先列舉最低點o,將縱座標大於等於o的點極角排序,然後dp求解

設dp(i,j)為以oi為最後一條邊,以oj為倒數第二條邊的最大空凸包,轉移方程為 dp[i][j] = max(dp[i][j], dp[j][k] + area);其中area為三角形oij的面積,k要小於j,注意oij要能形成三角形,三角形oij內無點(這裡不考慮邊上),邊oj上無點,向量i->k在向量i->j右面保證凸性

注意用int就可以,最後除2就好

#include <bits/stdc++.h>
using namespace std;
struct Point {
    int x, y;
    Point(int xx=0, int yy=0):x(xx),y(yy){}
    Point operator + (const Point &rhs) { return Point(x+rhs.x, y+rhs.y); }
    Point operator - (const Point &rhs) { return Point(x-rhs.x, y-rhs.y); }
}p[100], t[100];
int Dot(Point a, Point b) { return a.x*b.x+a.y*b.y; }
int Cross(Point a, Point 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) { return (Cross(a,b)==0?Dot(a,a)<Dot(b,b):Cross(a,b)>0); }
int T, n, m, dp[100][100], ans;
void solve() {
    for (int i = 0; i <= m; i++) for (int j = 0; j <= i; j++) dp[i][j] = 0;
    for (int i = 2; i <= m; i++) {
        for (int j = 1; j < i; j++) {
            if (Cross(t[i], t[j]) == 0) continue;
            bool emp = 1;
            for (int k = j + 1; k < i; k++) {
                if (Cross(t[k], t[i]) > 0 && Cross(t[j], t[k]) > 0 && Cross(t[i]-t[j], t[k]-t[j]) > 0) { emp = 0; break; }
            }
            if (!emp) continue;
            dp[i][j] = Cross(t[j], t[i]);
            if (Cross(t[j], t[j-1]) != 0) {
                for (int k = 0; k < j; k++) {
                    if (Cross(t[k]-t[i], t[j]-t[i]) > 0) dp[i][j] = max(dp[i][j], dp[j][k] + Cross(t[j], t[i]));
                }
            }
            ans = max(ans, dp[i][j]);
        }
    }
}
int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d%d", &p[i].x, &p[i].y);
        sort(p+1, p+1+n, cmp1);
        ans = 0;
        for (int i = 1; i <= n-2; i++, m = 0) {
            for (int j = i+1; j <= n; j++) t[++m] = p[j]-p[i];
            sort(t+1, t+1+m, cmp2);
            solve();
        }
        printf("%.1f\n", 1.0*ans/2.0);
    }
    return 0;
}