[POJ2079]Triangle(凸包+旋转卡壳)

来源:互联网 发布:矩阵张量积 知乎 编辑:程序博客网 时间:2024/05/22 05:08

题目描述

传送门
题意:给出一些点,求顶点在这些点上的面积最大的三角形

题解

其实这不算一个旋转卡壳吧…
很容易得出一个结论,最大的三角形一定是凸包上的边加上离它最远的点

反例也很容易举出:
这里写图片描述
所以我们只能固定两个点然后让第三个点单调
所以这道题实际上是O(n2)的,虽然有5w个点,但是凸包上的点远远达不到这个级别

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 100005const double eps=1e-9;int dcmp(double x){    if (x<=eps&&x>=-eps) return 0;    return (x>0)?1:-1;}struct Vector{    double x,y;    Vector(double X=0,double Y=0)    {        x=X,y=Y;    }    bool operator < (Vector const &a) const    {        return x<a.x||(x==a.x&&y<a.y);    }};typedef Vector Point;Vector operator + (Vector a,Vector b) {return Vector(a.x+b.x,a.y+b.y);}Vector operator - (Vector a,Vector b) {return Vector(a.x-b.x,a.y-b.y);}Vector operator * (Vector a,double b) {return Vector(a.x*b,a.y*b);}int n,top;double x,y,area;Point p[N],stack[N];double Cross(Vector a,Vector b){    return a.x*b.y-a.y*b.x;}void graham(){    sort(p+1,p+n+1);    top=0;    for (int i=1;i<=n;++i)    {        while (top>1&&dcmp(Cross(stack[top]-stack[top-1],p[i]-stack[top-1]))<=0)            --top;        stack[++top]=p[i];    }    int k=top;    for (int i=n-1;i>=1;--i)    {        while (top>k&&dcmp(Cross(stack[top]-stack[top-1],p[i]-stack[top-1]))<=0)            --top;        stack[++top]=p[i];    }    if (n>1) --top;}double rotating(){    if (top<=2) return 0;    if (top==3) return fabs(Cross(stack[2]-stack[1],stack[3]-stack[1])/2.0);    double ans=0;    for (int i=1;i<=top;++i)    {        int j=i%top+1;        int k=j%top+1;        while (dcmp(fabs(Cross(stack[i]-stack[j],stack[i]-stack[k]))-fabs(Cross(stack[i]-stack[j],stack[i]-stack[k%top+1])))<0) k=k%top+1;        while (i!=j&&j!=k&&i!=k)        {            ans=max(ans,fabs(Cross(stack[i]-stack[j],stack[i]-stack[k]))/2.0);            while (dcmp(fabs(Cross(stack[i]-stack[j],stack[i]-stack[k]))-fabs(Cross(stack[i]-stack[j],stack[i]-stack[k%top+1])))<0) k=k%top+1;            j=j%top+1;        }    }    return ans;}int main(){    while (~scanf("%d",&n))    {        if (n==-1) break;        for (int i=1;i<=n;++i)        {            scanf("%lf%lf",&x,&y);            p[i]=Point(x,y);        }        graham();        area=rotating();        printf("%.2lf\n",area);    }    return 0;}
0 0
原创粉丝点击