【最大空凸包 模板 计算几何 + DP】HDU - 6219 J - Empty Convex Polygons

探讨了在平面上给定一系列不重复的点时,如何寻找由这些点构成的不含任何其他点在内的最大面积凸多边形的问题。通过枚举凸包的左下角点并使用动态规划策略,计算出所有可能的最大空凸多边形面积。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

J - Empty Convex Polygons HDU - 6219 

Given a set of distinct points S on a plane, we define a convex hole to be a convex polygon having any of thegiven points as vertices and not containing any of the given points in its interior. In addition to the vertices, other given points may lie on the perimeter of the polygon. We want to find a convex hole as above forming the convexpolygon with the largest area. 

Input

This problem has several test cases. 
The first line of input contains an integer t (1 ≤ t ≤ 100) indicating the total number of cases. For each test case,the first line contains the integer n (3 ≤ n ≤ 50). Each of the following n lines describes a point with two integers x and y where -1000 ≤ x, y ≤ 1000. 
We guarantee that there exists at least one non-degenerated convex polygon. 

Output

For each test case, output the largest area of empty convex polygon, with the precision of 1 digit. 
Remark: The corollary of Pick’s theorem about the polygon with integer coordinates in that says the area of it iseither ends to .0 or .5.

Sample Input

4
3
0 0
1 0
0 1
5
0 0
1 0
2 0
0 1
1 1
5
0 0
3 0
4 1
3 5
-1 3
6
3 1
1 0
2 0
3 0
4 0
5 0

Sample Output

0.5
1.5
17.0
2.0

T组测试数据,每组n个点

求出n个点以其中若干个点为顶点的最大凸多边形面积,要求多边形内部不能有其它点

复杂度O(n^3)

思路:枚举凸包的左下角点,然后DP找出以这个点为起始位置能构成的最大空凸包面积,最后取这些空凸包面积的最大值为答案。DP过程:假设当前点OO为左下角,dp[i][j]dp[i][j]表示得是以OiOi,ijij为凸包的最后两条边所构成的凸包面积的最大值。状态转移方程:dp[i][j]=max(dp[i][j],triangle(O,i,j)+dp[j][k])dp[i][j]=max(dp[i][j],triangle(O,i,j)+dp[j][k])。时间复杂度:O(n4)

参考:

https://blog.youkuaiyun.com/Jaihk662/article/details/81988607

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
typedef struct Point
{
	int x, y;
	Point() {}
	Point(int x, int y): x(x),y(y) {}
	Point operator + (const Point &b) const {  return Point(x+b.x,y+b.y);  }
	Point operator - (const Point &b) const {  return Point(x-b.x,y-b.y);  }
	int operator * (const Point &b) const {  return x*b.y-y*b.x;  }
	int len() const {  return x*x+y*y;  }
	int operator < (const Point &a) const
	{
		if((*this)*a>0 || (*this)*a==0 && len()<a.len())
			return 1;
		return 0;
	}
}Point;
int n;
Point s[122], p[122];
int dp[122][122];
int Jud(int m)
{
	int ans, i, j, now, k, flag, S;
	memset(dp, 0, sizeof(dp));
	ans = 0;
	for(i=2;i<=m;i++)
	{
		now = i-1;
		while(now>=1 && p[i]*p[now]==0)
			now--;
		flag = 0;
		if(now==i-1)
			flag = 1;
		while(now>=1)
		{
			S = p[now]*p[i];
			k = now-1;
			while(k>=1 && (p[now]-p[i])*(p[k]-p[now])>0)
				k--;
			if(k>=1)
				S += dp[now][k];
			if(flag)
				dp[i][now] = S;
			ans = max(ans, S);
			now = k;
		}
		if(flag==0)
			continue;
		for(j=1;j<=i-1;j++)
			dp[i][j] = max(dp[i][j],dp[i][j-1]);
	}
	return ans;
}
int main(void)
{
	int T, i, j, m, ans;
	scanf("%d", &T);
	while(T--)
	{
		scanf("%d", &n);
		for(i=1;i<=n;i++)
			scanf("%d%d", &s[i].x, &s[i].y);
		ans = 0;
		for(i=1;i<=n;i++)
		{
			m = 0;
			for(j=1;j<=n;j++)
			{
				if(s[j].y>s[i].y || s[j].y==s[i].y && s[j].x>=s[i].x)
					p[++m] = s[j]-s[i];
			}
			sort(p+1, p+m+1);
			ans = max(ans, Jud(m));
		}
		printf("%.1f\n", ans/2.0);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值