hdu6219(最大空凸包)

题意:

  给一些点,求出一个最大的空凸包,这个凸包里没有任何给定点且要求这个凸包面积最大

分析:

  枚举凸包左下角的点,然后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

hdu6219(最大空凸包)的相关文章

HDU6219/POJ1259 [ICPC2017沈阳]Empty Convex Polygons 最大空凸包

Empty Convex Polygons Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 538    Accepted Submission(s): 138 Problem Description Given a set of distinct points S on a plane, we define a convex ho

Game of Taking Stones &amp;&amp; POJ1259 /// 最大空凸包 几何+DP

题目大意: 给定n个点 求出这n个点中最大空凸包的面积 只放个模板 一份模板过两题(滑稽 这个讲解够详细了 https://blog.csdn.net/nyroro/article/details/45268767 #include <stdio.h> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const double eps=1e-8; dou

O(n^3)求最大空凸包模板(2017沈阳icpc-C Empty Convex Polygons )

题目链接:https://vjudge.net/contest/358714#problem/C 题意:求最大空凸包的面积,点的个数n<=50. 思路: 参考链接:https://blog.csdn.net/cdsszjj/article/details/79366813 计算几何+DP. 首先枚举凸包最左下角的点O,忽略O下面的点,对其它点进行极角排序. 然后枚举凸包上的最后一个点i,用dp[i][j]表示以三角形Oij为凸包的最后一块三角形的最大空凸包的面积.那么可以得到转移方程: dp[i

POJ1259 The Picnic 最大空凸包问题 DP

POJ1259 给定平面上100个点 求一个最大的凸包,使得它不包含其中任意点,且凸包的顶点是题目所给的点. 枚举凸包左下角的点,顺时针枚举第二个点, 用opt[i][j]记录 i作为第二个点, 且第三个点k在向量i->j的右手(保持凸性) 显然相邻的凸包可以用来转移, opt[j][h]可以加入opt[i][j]  大致思想就是这样 看Solve函数. #include<iostream> #include<cstdio> #include<cstdlib> #

最大空凸包模板

inline double sgn(double x, double y) { return fabs(x-y)<eps; } inline int sgn(int x, int y) { return x==y; } struct point { double x,y; }; double cross(point a, point b, point o) { return (a.x-o.x)*(o.y-b.y)-(a.y-o.y)*(o.x-b.x); } double dist(point

最大空凸包

#pragma GCC optimize(2) #pragma GCC optimize(3, "Ofast", "inline") #include<bits/stdc++.h> #define ll long long #define met(a, x) memset(a,x,sizeof(a)) using namespace std; const double pi = acos(-1.0); typedef struct Point { int

Voronoi图和Delaunay三角形和凸包

写一下最近写的一点东西... 最近在上算法课,上课老师讲到了维诺图,自己觉得很有意思就研究了一下,并用java写了一个简单的se程序用来显示维诺图和Delaunay三角形还有凸包. 首先介绍一下凸包,凸包在数学里是很常见的,给定一些点,然后找出包含这些的最小凸包,一般是这么做的.至于凸包的定义维基百科或者百度都行,自己查一查就知道,通俗的讲就是延长每一条边,剩下的图形总在边的一边. (界面有点丑) 这边给出一下我程序运行出来的凸包 然后是Delaunay三角形,这个三角形是这样的,可以在凸包里面

POJ3528 HDU3662 三维凸包模板

POJ3528 HDU3662 第一道题 给定若干点 求凸包的表面积,第二题 给定若干点就凸包的面数. 简单说一下三维凸包的求法,首先对于4个点假设不共面,确定了唯一四面体,对于一个新的点,若它不在四面体内,为了让它进入凸包, 则对于所有凸包上的边,若边的一面是该点可以看到的而另一面看不到,则该点与该边构成的面要加入凸包. 模板代码非常清晰, #include<stdio.h> #include<algorithm> #include<string.h> #includ

关于2016.12.12——T1的反思:凸包的意义与应用

2016.12.12 T1 给n个圆,保证圆圆相离,求将圆围起来的最小周长.n<=100 就像上图.考场上,我就想用切线的角度来做凸包.以圆心x,y排序,像点凸包一样,不过用两圆之间的下切线角度来判断. 这就是下切线(我自己瞎编的名字): 好像是对的啊: 然后我就保证必AC的希望,用这种写法交了,然后就只得了N=2的暴力分... 自以为是正解,却落得如此下场... 为什么?这样不对吗?借用学长的力量,果然被Hack掉了: 这种情况,圆心排序后,检测的顺序并不是圆上的切点的顺序,自然就会挂. 蓝瘦