1. 程式人生 > >【最大空凸包 模板 計算幾何 + DP】HDU

【最大空凸包 模板 計算幾何 + DP】HDU

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)

參考:

#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;
}