旋转卡壳 POJ 2079 Triangle

Triangle
Time Limit: 3000MS Memory Limit: 30000K
Total Submissions: 8008 Accepted: 2363

Description

Given n distinct points on a plane, your task is to find the triangle that have the maximum area, whose vertices are from the given points.

Input

The input consists of several test cases. The first line of each test case contains an integer n, indicating the number of points on the plane. Each of the following n lines contains two integer xi and yi, indicating the ith points. The last line of the input is an integer −1, indicating the end of input, which should not be processed. You may assume that 1 <= n <= 50000 and −10 4  <= xi, yi <= 10 4  for all i = 1 . . . n.

Output

For each test case, print a line containing the maximum area, which contains two digits after the decimal point. You may assume that there is always an answer which is greater than zero.

Sample Input

3
3 4
2 6
2 7
5
2 6
3 9
2 0
8 0
6 5
-1

Sample Output

0.50
27.00

Source

 

题意:给出一个点集,求出最大面积的三角形的面积。

 

思路:最大三角形的三个顶点一定在凸包上面。那么假设我们选了两个点,其实另外一点就已经确定了,就在离这条直线最远的定点。怎么找?用旋转卡壳的思想,我们假设前一个已经找到了对应的第三个点,那么我们将第二个点逆时针换一个,此时,原来第三个点的索引我们不需要变为从0开始重新找一遍,我们的第三个点只需要继续往逆时针方向走就行了,知道离直线最远,停下来,算一下面积,然后继续让第二个点走一个点,继续重复上面的操作,当走完一圈的时候,我们的第一个点逆时针走一个点,然后第二个点变为第一个点的下一个点,第三个点变为第二个点的下一个店。继续以上的操作就行了。 感觉复杂度应该是O(n^2)

 

 

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=50000+5;
#define LL long long
struct Point
{
    LL x,y;
    Point(LL x=0,LL y=0)
    :x(x),y(y) { }
    bool operator<(const Point&p) const
    {
        return x<p.x||(x==p.x&&y<p.y);
    }
    bool operator==(const Point&p) const
    {
        return x==p.x&&y==p.y;
    }
};

typedef Point Vector;

Vector operator+(const Vector&a,const Vector&b) { return Vector(a.x+b.x,a.y+b.y); }
Vector operator-(const Vector&a,const Vector&b) { return Vector(a.x-b.x,a.y-b.y); }

LL Dot(const Vector&a,const Vector&b) { return a.x*b.x+a.y*b.y; }
LL Cross(const Vector&a,const Vector&b) { return a.x*b.y-a.y*b.x; }

int Convexhull(Point *p,int n,Point *ch)
{
    sort(p,p+n);
    n=unique(p,p+n)-p;
    int m=0;
    for(int i=0;i<n;++i) {
        while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-1])<=0) --m;
        ch[m++]=p[i];
    }
    int k = m;
    for(int i=n-2;i>=0;--i) {
        while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-1])<=0) --m;
        ch[m++]=p[i];
    }
    if(n>1) --m;
    return m;
}

double RotateCalipers(Point*p,int n)
{
    p[n]=p[0];
    if(n<3) return 0;
    int j,k;
    double ret=0;
    for(int i=0;i<n;++i) {
        j=(i+1)%n,k=(i+2)%n;
        for(;;) {
            while(Cross(p[j]-p[i],p[k+1]-p[k])>0) k=(k+1)%n;
            if(k==j || k==i) break;
            double S=Cross(p[j]-p[i],p[k]-p[i]);
            if(S>ret) ret=S;
            j=(j+1)%n;
        }
    }
    return ret/2;
}

Point p[maxn],hull[maxn];
int n;

void input()
{
    for(int i=0;i<n;++i) scanf("%I64d%I64d",&p[i].x,&p[i].y);

}

void solve()
{
    int m=Convexhull(p,n,hull);
    double ans=RotateCalipers(hull,m);
    printf("%.2lf\n",ans);
}

int main()
{
    while(scanf("%d",&n)==1)
    {
        if(n==-1) return 0;
        input();
        solve();
    }
    return 0;
}


 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值