https://vjudge.net/contest/324256#problem/L
题意:给一堆点,求最大空凸包面积。
思路:枚举凸包左下角点O,dp找出以这个点为起始位置能构成的最大空凸包面积,用dp[i][j]表示以Oi和ij为凸包最后两边所构成凸包面积的最大值。
dp[i][j] = max(dp[i][j],triangle(O,i,j)+dp[j][k])
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; 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(){ int t,i,j,m,ans; cin>>t; while(t--){ cin>>n; for(i=1;i<=n;i++) cin>>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+1+m); ans = max(ans,jud(m)); } printf("%.1f ",ans/2.0); } return 0; }