【模板】旋转卡壳求 面积最大的三角形 poj2079

题目链接:https://vjudge.net/problem/POJ-2079

graham跑的巨慢,Andrew跑的巨快。还好写。

有两种写法。

旋转卡壳枚举三个点的(94ms)

 1 /*************************************************************************
 2     > File Name: poj2079.cpp
 3 # File Name: poj2079.cpp
 4 # Author : xiaobuxie
 5 # QQ : 760427180
 6 # Email:[email protected]
 7 # Created Time: 2019年10月12日 星期六 17时55分28秒
 8  ************************************************************************/
 9
10 #include<iostream>
11 #include<cstdio>
12 #include<map>
13 #include<cmath>
14 #include<cstring>
15 #include<set>
16 #include<queue>
17 #include<vector>
18 #include<algorithm>
19 using namespace std;
20 typedef long long ll;
21 #define inf 0x3f3f3f3f
22 #define pq priority_queue<int,vector<int>,greater<int> >
23 ll gcd(ll a,ll b){
24     if(a<b) return gcd(b,a);
25     return b==0?a:gcd(b,a%b);
26 }
27
28 const int N = 5e4+9;
29 struct Point{
30     double x,y;
31     bool operator < (const Point& b)const{
32         return x<b.x || (x==b.x && y<b.y);
33     }
34     Point operator - (const Point& b)const{
35         return (Point){x-b.x,y-b.y};
36     }
37     double operator ^ (const Point& b)const{
38         return x*b.y - b.x*y;
39     }
40 }p[N],ch[N];
41 int n;
42 inline void init(){
43     for(int i =0 ;i<n;++i) scanf("%lf %lf",&p[i].x,&p[i].y);
44 }
45 inline int Andrew(){
46     sort(p,p+n);
47     int m = 0;
48     for(int i = 0; i < n;++i){
49         while( m>1 && ((p[i] - ch[m-2]) ^ (ch[m-1] - ch[m-2])) >=0) --m;
50         ch[m++] = p[i];
51     }
52     int k = m;
53     for(int i = n-2;i >= 0;--i){
54         while( m>k && ((p[i] - ch[m-2]) ^ (ch[m-1] - ch[m-2])) >=0) --m;
55         ch[m++] = p[i];
56     }
57     if(n>1) --m;
58     return m;
59 }
60 inline void rotate(){
61     double ans =0;
62     int m = Andrew();
63     int a = 1, b = 2;
64     for(int i = 0; i < m ;++i){
65         while( ((ch[a] - ch[i]) ^ (ch[(b+1)%m] - ch[i])) > ((ch[a] - ch[i]) ^ (ch[b] - ch[i]))){
66             b = (b+1)%m;
67         }
68         ans = max(ans,( (ch[a] - ch[i]) ^ (ch[b] - ch[i]) ));
69
70         while( ((ch[(a+1)%m] - ch[i]) ^ (ch[b] - ch[i])) > ((ch[a] - ch[i]) ^ (ch[b] - ch[i]))){
71             a = (a+1)%m;
72         }
73         ans = max(ans,( (ch[a] - ch[i]) ^ (ch[b] - ch[i]) ));
74     }
75     ans /= 2.0;
76     printf("%.2f\n",ans);
77 }
78 int main(){
79     while(~scanf("%d",&n) && n!=-1){
80         init();
81         rotate();
82     }
83     return 0;
84 }

枚举两点之间差,再枚举第三个点的(391ms)

 1 /*************************************************************************
 2     > File Name: poj2079.cpp
 3 # File Name: poj2079.cpp
 4 # Author : xiaobuxie
 5 # QQ : 760427180
 6 # Email:[email protected]
 7 # Created Time: 2019年10月12日 星期六 17时55分28秒
 8  ************************************************************************/
 9
10 #include<iostream>
11 #include<cstdio>
12 #include<map>
13 #include<cmath>
14 #include<cstring>
15 #include<set>
16 #include<queue>
17 #include<vector>
18 #include<algorithm>
19 using namespace std;
20 typedef long long ll;
21 #define inf 0x3f3f3f3f
22 #define pq priority_queue<int,vector<int>,greater<int> >
23 ll gcd(ll a,ll b){
24     if(a<b) return gcd(b,a);
25     return b==0?a:gcd(b,a%b);
26 }
27
28 const int N = 5e4+9;
29 struct Point{
30     double x,y;
31     bool operator < (const Point& b)const{
32         return x<b.x || (x==b.x && y<b.y);
33     }
34     Point operator - (const Point& b)const{
35         return (Point){x-b.x,y-b.y};
36     }
37     double operator ^ (const Point& b)const{
38         return x*b.y - b.x*y;
39     }
40 }p[N],ch[N];
41 int n;
42 inline void init(){
43     for(int i =0 ;i<n;++i) scanf("%lf %lf",&p[i].x,&p[i].y);
44 }
45 inline int Andrew(){
46     sort(p,p+n);
47     int m = 0;
48     for(int i = 0; i < n;++i){
49         while( m>1 && ((p[i] - ch[m-2]) ^ (ch[m-1] - ch[m-2])) >=0) --m;
50         ch[m++] = p[i];
51     }
52     int k = m;
53     for(int i = n-2;i >= 0;--i){
54         while( m>k && ((p[i] - ch[m-2]) ^ (ch[m-1] - ch[m-2])) >=0) --m;
55         ch[m++] = p[i];
56     }
57     if(n>1) --m;
58     return m;
59 }
60 inline void rotate(){
61     double ans =0;
62     int m = Andrew();
63     ch[m] = ch[0];
64     for(int ad = 1; ad <= m/2;++ad){
65         int now = (ad+1) % m;
66         for(int i = 0; i < m;++i){
67             int j = (i+ad) % m;
68             while( ((ch[j] - ch[i]) ^ (ch[now] - ch[i])) < ((ch[j] - ch[i]) ^ (ch[now+1] - ch[i]))){
69                     ++now;
70                     if(now == m) now = 0;
71             }
72             ans = max(ans,( (ch[j] - ch[i]) ^ (ch[now] - ch[i]) ));
73         }
74     }
75     ans /= 2.0;
76     printf("%.2f\n",ans);
77 }
78 int main(){
79     while(~scanf("%d",&n) && n!=-1){
80         init();
81         rotate();
82     }
83     return 0;
84 }

原文地址:https://www.cnblogs.com/xiaobuxie/p/11666798.html

时间: 2024-10-10 12:01:20

【模板】旋转卡壳求 面积最大的三角形 poj2079的相关文章

poj 2079 Triangle,旋转卡壳求点集的最大三角形

给出一个点集,求顶点在点集中的最大的三角形面积. 我们知道这三角形的三个点肯定在凸包上,我们求出凸包之后不能枚举,因为题目n比较大,枚举的话要O(n^3)的数量级,所以采用旋转卡壳的做法: 首先枚举三角形的第一个顶点i, 初始化第二个顶点j=i+1和第三个顶点k=j+1,对k进行循环,直到找到第一个k使得cross(i,j,k)>cross(i,j,k+1),如果k==i进入下一次循环. 对j,k进行旋转,每次循环之前更新最大值,然后固定一个j,同样找到一个k使得cross(i,j,k)>cr

HDOJ 2202 最大三角形 凸包旋转卡壳求最大三角形面积

凸包旋转卡壳求最大三角形面积 最大三角形 Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3316    Accepted Submission(s): 1119 Problem Description 老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角

hdu 3934&amp;&amp;poj 2079 (凸包+旋转卡壳+求最大三角形面积)

链接:http://poj.org/problem?id=2079 Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 8173   Accepted: 2423 Description Given n distinct points on a plane, your task is to find the triangle that have the maximum area, whose vertices

模板 旋转卡壳 凸包

模板 旋转卡壳 凸包 好早以前看的,现在再记下来吧,当做复习一遍. 那么,先提一下最基本最暴力的求凸包直径的方法吧---枚举...好吧..很多问题都可以用 枚举 这个“万能”的方法来解决,过程很简单方便是肯定的,不过在效率上就要差很远了.  要求一个点集的直径,即使先计算出这个点集的凸包,然后再枚举凸包上的点对,这样来求点集直径的话依然会在凸包上点的数量达到O(n)级别是极大的降低它的效率,也浪费了凸包的优美性质.不过在数据量较小或者很适合时,何必要大费周折的用那些麻烦复杂的算法呢,枚举依然是解

bzoj1069: [SCOI2007]最大土地面积 凸包+旋转卡壳求最大四边形面积

在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. 题解:先求出凸包,O(n)枚举旋转卡壳,O(n)枚举另一个点,求最大四边形面积 /************************************************************** Problem: 1069 User: walfy Language: C++ Result: Accepted Time:892 ms Memory:1360 kb ****

bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包

[HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 2081  Solved: 920[Submit][Status][Discuss] Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, 输出所求矩形的面积和四个顶点坐标 Input 第一行为一个整数n(3<=n<=50000) 从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计

Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离

\(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接这两个岛屿.为了把成本降到最低,国王要求你,主教,找到两个岛屿边界之间最小的距离. \(\color{#0066ff}{输入格式}\) 输入由几个测试用例组成. 每个测试用两个整数n,m(3≤n,m≤10000)开始 接下来的n行中的每一行都包含一对坐标,用来描述顶点在一个凸多边形中的位置. 下一条

POJ3608(旋转卡壳--求两凸包的最近点对距离)

分析:以下内容来自:http://blog.csdn.net/acmaker/article/details/3178696 考虑如下的算法, 算法的输入是两个分别有m和n个顺时针给定顶点的凸多边形P和Q. 1.计算P上y坐标值最小的顶点(称为 yminP )和Q上y坐标值最大的顶点(称为 ymaxQ). 2.为多边形在 yminP 和 ymaxQ 处构造两条切线 LP 和 LQ 使得他们对应的多边形位于他们的右侧.   此时 LP 和 LQ 拥有不同的方向, 并且 yminP 和 ymaxQ

凸包与旋转卡壳

关于凸包的几个名词: 1.支撑线: 如果一条直接L通过凸多边形P的一个顶点,且多边形在这条直线的一侧,则称L是P的支撑线 2.对踵点: 如果过凸包上的两个点可以画一对平行线,使得凸包上左右的点都夹在两条平行线之间或者 落在平行线上那么两个点称为一对对踵点.两条平行的支撑线所过的两点就是一对对踵点.可以 证明一个凸n边形的对踵点最多有3n/2对 3.凸多边形的直径: 将一个多边形上任意两点间的距离的最大值定义为多边形的直径.确定这个直径的点对数可能 多于一对. 旋转卡壳求直径的步骤: step1.