6219 Empty Convex Polygons——dp+幾何
阿新 • • 發佈:2019-01-08
首先列舉最低點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; }