CodeForces 682E Alyona and Triangles【最大三角形 旋转卡壳or迭代】
2018-02-25 14:44
441 查看
题目大意:
给出n个点,任意三个点组成的三角形面积不超过S,S大于n个点可以组成三角形的最大面积;构造一个大三角形覆盖上述所有n个点,并且面积不超过4S;
解题思路:
不得不说思路很巧妙,不过题目中的S取值也相当于给了个暗示。结论:
先求出最大三角形ABCABC,再以abc分别作为三边中点所得三角形A′B′C′A′B′C′即是所求三角形。如图:证明:
首先易得SΔA′B′C′=4SΔABC≤4SSΔA′B′C′=4SΔABC≤4S。再证明所有点都会被ΔA′B′C′ΔA′B′C′包含,考虑反证法。
假设有一个点DD不在ΔA′B′C′ΔA′B′C′中,比如在A′B′A′B′右侧,那么有
dis(D,AB)>dis(C,AB)dis(D,AB)>dis(C,AB),
所以SΔABC<SΔABDSΔABC<SΔABD,这与ΔABCΔABC是最大三角形矛盾,所以不成立。
得证。
求最大三角形的方法有两种,第一种是旋转卡壳,第二种是迭代,复杂度都是O(n2)O(n2),不过不知道迭代复杂度是怎么证明的。
AC代码:
旋转卡壳版:#include<bits/stdc++.h> #define ll long long using namespace std; const int N=5005; struct point { int x,y; point(){} point(int _x,int _y):x(_x),y(_y){} inline friend point operator - (const point &a,const point &b) {return point(a.x-b.x,a.y-b.y);} inline friend point operator + (const point &a,const point &b) {return point(a.x+b.x,a.y+b.y);} inline friend ll operator * (const point &a,const point &b) {return 1ll*a.x*b.y-1ll*a.y*b.x;} inline ll dis(){return 1ll*x*x+1ll*y*y;} }p ,A,B,C; int n,top; ll S; inline bool cmp(const point &a,const point &b) { ll res=(a-p[1])*(b-p[1]); if(res)return res>0; return (a-p[1]).dis()<(b-p[1]).dis(); } inline ll area(int i,int j,int k) { return abs((p[j]-p[i])*(p[k]-p[i])); } void graham() { for(int i=2;i<=n;i++) if((p[i].x<p[1].x)||(p[i].x==p[1].x&&p[i].y<p[1].y))swap(p[1],p[i]); sort(p+2,p+n+1,cmp),top=1; for(int i=2;i<=n;i++) { while(top>1&&(p[top-1]-p[i])*(p[top]-p[i])<0)top--; p[++top]=p[i]; }n=top; } int main() { //freopen("lx.in","r",stdin); scanf("%d%lld",&n,&S); for(int i=1;i<=n;i++)scanf("%d%d",&p[i].x,&p[i].y); graham(); S=0;point a,b,c; for(int i=1;i<=n-2;i++) for(int j=i+1,k=j+1;j<=n-1;j++) { while(k<=n&&area(i,j,k+1)>=area(i,j,k))k++; if(area(i,j,k)>S)S=area(i,j,k),a=p[i],b=p[j],c=p[k]; } A=a+(b-c),B=b+(c-a),C=c+(a-b); printf("%d %d\n%d %d\n%d %d\n",A.x,A.y,B.x,B.y,C.x,C.y); return 0; }
迭代版:
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=5005; struct point { int x,y; point(){} point(int _x,int _y):x(_x),y(_y){} inline friend point operator - (const point &a,const point &b) {return point(a.x-b.x,a.y-b.y);} inline friend point operator + (const point &a,const point &b) {return point(a.x+b.x,a.y+b.y);} inline friend ll operator * (const point &a,const point &b) {return 1ll*a.x*b.y-1ll*a.y*b.x;} }p ,A,B,C; int n,top; ll S; inline ll area(int i,int j,int k) { return abs((p[j]-p[i])*(p[k]-p[i])); } int main() { //freopen("lx.in","r",stdin); scanf("%d%lld",&n,&S); for(int i=1;i<=n;i++)scanf("%d%d",&p[i].x,&p[i].y); int a=1,b=2,c=3;bool bz=1; S=area(a,b,c); while(bz) { bz=0; for(int i=1;i<=n;i++) { ll tmp; tmp=area(a,b,i); if(tmp>S)S=tmp,c=i,bz=1; tmp=area(a,i,c); if(tmp>S)S=tmp,b=i,bz=1; tmp=area(i,b,c); if(tmp>S)S=tmp,a=i,bz=1; } } A=p[a]+(p[b]-p[c]),B=p[b]+(p[c]-p[a]),C=p[c]+(p[a]-p[b]); printf("%d %d\n%d %d\n%d %d\n",A.x,A.y,B.x,B.y,C.x,C.y); return 0; }
相关文章推荐
- POJ 2079 Triangle(旋转卡壳计算平面点集最大三角形面积)
- hdu2202 最大三角形(旋转卡壳)
- POJ 2079 Triangle(凸包+旋转卡壳,求最大三角形面积)
- 最大三角形 HDU - 2202 旋转卡壳模板
- HDU 2202 最大三角形 (凸包+旋转卡壳)
- poj 2079 Triangle,旋转卡壳求点集的最大三角形
- POJ 2079 Triangle (凸包中的最大三角形&旋转卡壳)
- POJ 2079 Triangle(凸包_旋转卡壳之最大三角形面积)
- POJ 2079 Triangle(凸包+旋转卡壳求最大三角形面积)
- HDOJ 2202 最大三角形 凸包旋转卡壳求最大三角形面积
- CodeForces 682E Alyona and Triangles (计算几何)
- ZOJ 2419-- Triangle-凸包+旋转卡壳求最大面积三角形(计算几何)
- hdu 最大三角形(凸包+旋转卡壳)
- POJ2079 旋转卡壳 凸包内最大三角形
- hdu 3934&&poj 2079 (凸包+旋转卡壳+求最大三角形面积)
- HDU 3934 Summer holiday 旋转卡壳 最大三角形面积
- Codeforces Round #358 (Div. 2) E. Alyona and Triangles (找面积最大三角形)
- poj2079 Triangle (旋转卡壳之最大三角形)
- POJ 2079 求最大三角形面积 (凸包+旋转卡壳)
- Codeforces Round #358 (Div. 2) E 计算几何 旋转卡壳求最大三角形面积