题意:
给一些点,求出一个最大的空凸包,这个凸包里没有任何给定点且要求这个凸包面积最大
分析:
枚举凸包左下角的点,然后dp[i][j]表示凸包的最后两条边是j->i和i->O情况下凸包的面积最大值,这个是O(n^4)的
可以利用凸性求个前缀和来完成O(1)的转移
具体看这里:https://blog.csdn.net/nyroro/article/details/45268767
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=50; 4 typedef int db; 5 struct Point 6 { 7 /*点类*/ 8 db x,y; 9 Point(){} 10 Point(db _x,db _y):x(_x),y(_y){} 11 void input() 12 { 13 scanf("%d%d",&x,&y); 14 } 15 Point operator + (const Point &t)const 16 { 17 return Point(x+t.x,y+t.y); 18 } 19 Point operator - (const Point &t)const 20 { 21 return Point(x-t.x,y-t.y); 22 } 23 db operator * (const Point &t)const 24 { 25 return x*t.y-y*t.x; 26 } 27 db len()const 28 { 29 return x*x+y*y; 30 } 31 bool operator < (const Point &t) const 32 { 33 if((*this)*t!=0) return (*this)*t>0; 34 return len()<t.len(); 35 } 36 }p[maxn+5],a[maxn+5]; 37 int n,m; 38 int ans; 39 int dp[maxn+5][maxn+5],sum[maxn+5][maxn+5]; 40 void work(int n) 41 { 42 memset(dp,0,sizeof(dp)); 43 memset(sum,0,sizeof(sum)); 44 for(int i=2;i<=n;++i) 45 { 46 int j=i-1; 47 while(j>=1&&a[i]*a[j]==0) --j; 48 bool flag=0; 49 if(j==i-1) flag=1; 50 while(j>=1) 51 { 52 int k=j-1; 53 int res=a[j]*a[i]; 54 while(k>=1&&(a[j]-a[i])*(a[k]-a[j])>0) --k; 55 if(k) res+=sum[j][k]; 56 if(flag) dp[i][j]=res; 57 ans=max(ans,res); 58 j=k; 59 } 60 sum[i][1]=dp[i][1]; 61 for(int j=2;j<i;++j) sum[i][j]=max(dp[i][j],sum[i][j-1]); 62 } 63 } 64 int main() 65 { 66 int T; 67 scanf("%d",&T); 68 while(T--) 69 { 70 scanf("%d",&n); 71 for(int i=1;i<=n;++i) p[i].input(); 72 ans=0; 73 for(int i=2;i<=2;++i) 74 { 75 m=0; 76 for(int j=1;j<=n;++j) if(p[j].y>p[i].y||(p[i].y==p[j].y&&p[j].x>=p[i].x)) a[++m]=p[j]-p[i]; 77 //for(int i=1;i<=m;++i) printf("%d %d\n",a[i].x,a[i].y); 78 //printf("\n"); 79 sort(a+1,a+m+1); 80 //for(int i=1;i<=m;++i) printf("%d %d\n",a[i].x,a[i].y); 81 work(m); 82 } 83 //printf("%d\n",ans); 84 printf("%.1f\n",1.0*ans/2); 85 } 86 return 0; 87 }
原文地址:https://www.cnblogs.com/wmrv587/p/8997768.html
时间: 2024-10-08 10:42:04