问题:给定一个点集,求一个面积最大的凸多边形,凸多边形中是空的没有其他点
最大空凸包板子题
对于每一个点O,dp[i][j]表示以Oi和ij为凸包最后两边所构成凸包面积的最大值。
dp[i][j] = max(dp[i][j],Δ(O,i,j)+dp[j][k])
枚举O点是o(n)时间复杂度,dp枚举i,j是o(n^2)时间复杂度,总时间复杂度是o(n^3)
然后因为题目给的都是整数坐标点,那么答案的小数点要么是.0要么是.5,直接输出一位就行
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
double dp[N][N];
double eq(double x, double y)
{
return fabs(x - y) < 1e-6;
}
struct point
{
double x, y;
};
double d1(point a, point b, point o)
{
return (a.x - o.x) * (o.y - b.y) - (a.y - o.y) * (o.x - b.x);
}
double d2(point a, point b)
{
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
point o;
bool cmp(point a, point b) // 极角排序
{
if (eq(d1(a, b, o), 0.0))
{
return d2(a, o) < d2(b, o);
}
return d1(a, o, b) > 0;
}
double empty_convex(point *p, int pn)
{
double ans = 0;
for (int i = 0; i < pn; i++)
{
for (int j = 0; j < pn; j++)
{
dp[i][j] = 0;
}
}
for (int i = 0; i < pn; i++)
{
int j = i - 1;
while (j >= 0 && eq(d1(p[i], p[j], o), 0.0))
j--;
bool flag = j == i - 1;
while (j >= 0)
{
int k = j - 1;
while (k >= 0 && d1(p[i], p[k], p[j]) > 0)
k--;
double area = fabs(d1(p[i], p[j], o)) / 2;
if (k >= 0)
area += dp[j][k];
if (flag)
dp[i][j] = area;
ans = max(ans, area);
j = k;
}
if (flag)
{
for (int j = 1; j < i; j++)
{
dp[i][j] = max(dp[i][j], dp[i][j - 1]);
}
}
}
return ans;
}
double solve(point *p, int pn)
{
point data[N];
double ans = 0;
for (int i = 0; i < pn; i++)
{
o = p[i];
int dn = 0;
for (int j = 0; j < pn; j++)
{
if (p[j].y > o.y || (p[j].y == o.y && p[j].x >= o.x))
data[dn++] = p[j];
}
sort(data, data + dn, cmp);
ans = max(ans, empty_convex(data, dn));
}
return ans;
}
point p[110];
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> p[i].x >> p[i].y;
cout << fixed << setprecision(1) << solve(p, n) << endl;
}
}