1. 程式人生 > >hdu6219(最大空凸包)

hdu6219(最大空凸包)

memset pri PE .net src tro DC http --

題意:

  給一些點,求出一個最大的空凸包,這個凸包裏沒有任何給定點且要求這個凸包面積最大

分析:

  枚舉凸包左下角的點,然後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 }
View Code

hdu6219(最大空凸包)