POJ 2079 Triangle [旋转卡壳]

Triangle

Time Limit: 3000MS   Memory Limit: 30000K
Total Submissions: 9525   Accepted: 2845

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 −104 <= xi, yi <= 104 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

Shanghai 2004 Preliminary



选三个点三角形面积最大

这三个点一定在凸包上

可以O(n),猜i,j,k单调,然后和旋转卡壳一样枚举i,先让k跑,再让j跑

事实证明貌似真的单调,discuss里的数据并不能卡掉我的程序....

注意:跑的时候用面积判断是不是跑到下一个

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int N=5e4+5;
const double eps=1e-8;

inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();}
    return x*f;
}

inline int sgn(double x){
    if(abs(x)<eps) return 0;
    else return x<0?-1:1;
}

struct Vector{
    double x,y;
    Vector(double a=0,double b=0):x(a),y(b){}
    bool operator <(const Vector &a)const{
        return sgn(x-a.x)<0||(sgn(x-a.x)==0&&sgn(y-a.y)<0);
    }
};
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);}
Vector operator /(Vector a,double b){return Vector(a.x/b,a.y/b);}
bool operator ==(Vector a,Vector b){return sgn(a.x-b.x)==0&&sgn(a.y-b.y)==0;}
double Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}

double Len(Vector a){return sqrt(Dot(a,a));}
double Len2(Vector a){return Dot(a,a);}
double DisTL(Point p,Point a,Point b){
    Vector v1=p-a,v2=b-a;
    return abs(Cross(v1,v2)/Len(v2));
}
int ConvexHull(Point p[],int n,Point ch[]){
    sort(p+1,p+1+n);
    int m=0;
    for(int i=1;i<=n;i++){
        while(m>1&&sgn(Cross(ch[m]-ch[m-1],p[i]-ch[m-1]))<=0) m--;
        ch[++m]=p[i];
    }
    int k=m;
    for(int i=n-1;i>=1;i--){
        while(m>k&&sgn(Cross(ch[m]-ch[m-1],p[i]-ch[m-1]))<=0) m--;
        ch[++m]=p[i];
    }
    if(n>1) m--;
    return m;
}
double RotatingCalipers(Point p[],int n){
    if(n<=2) return 0;
    if(n==3) return abs(Cross(p[3]-p[1],p[2]-p[1]));
    int j=2,k=3;
    double ans=0;
    p[n+1]=p[1];
    for(int i=1;i<=n;i++){
        while(sgn(DisTL(p[k],p[i],p[j])-DisTL(p[k+1],p[i],p[j]))<=0) k=k%n+1;
        //while(sgn(abs(Cross(p[k]-p[i],p[k]-p[j]))-abs(Cross(p[k+1]-p[i],p[k+1]-p[j])))<=0) k=k%n+1;
        ans=max(ans,abs(Cross(p[k]-p[i],p[k]-p[j])));
        //while(sgn(DisTL(p[k],p[i],p[j])-DisTL(p[k],p[i],p[j+1]))<=0) j=j%n+1;
        while(abs(Cross(p[k]-p[i],p[k]-p[j]))-abs(Cross(p[k]-p[i],p[k]-p[j+1]))<=0) j=j%n+1;
        ans=max(ans,abs(Cross(p[k]-p[i],p[k]-p[j])));
    }
    return ans;
}

int n;
Point p[N],ch[N];
int main(int argc, const char * argv[]) {
    while(true){
        n=read();if(n==-1) break;
        for(int i=1;i<=n;i++) p[i].x=read(),p[i].y=read();
        n=ConvexHull(p,n,ch);
        double ans=RotatingCalipers(ch,n);
        printf("%.2f\n",ans/2);
    }
}
时间: 2024-10-03 13:30:09

POJ 2079 Triangle [旋转卡壳]的相关文章

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

poj 2079 Triangle 凸包+旋转卡壳

题意: 给平面上n个点,求这n个点组成的最大三角形面积. 分析: 旋转卡壳,但要注意和求平面最远点对的区别,最大三角形的边不一定在凸包上的,也贴出以前写的求平面最远点对的poj 2187代码作为对比. 代码: //poj 2079 //sep9 #include <iostream> #include <algorithm> using namespace std; const int maxN=50012; struct P { int x,y; }pnt[maxN],cnt[m

poj 2079 Triangle(旋转卡壳)

Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 8917   Accepted: 2650 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

●POJ 2079 Triangle

题链: http://poj.org/problem?id=2079 题解: 计算几何,凸包,旋转卡壳 复杂度O(N^2),(O(N)什么的就不说了,我觉得我看过的O(N)方法正确性都有问题,虽然有些AC了,那应该是鲁棒性太强了,谁叫他们非要每挪动一步都取MAX的呢) 做法: (三角形的三个顶点在凸包的顶点上,同时显然三角形的底边不一定为凸包的边啦!) 枚举i,j两点,使得有向线段$\vec{ij}$作为三角形底边. 然后在有向线段$\vec{ij}$的右侧区域(凸包上),寻找k点使得三角形ij

【旋转卡壳】POJ 2079 Triangle

通道:http://poj.org/problem?id=2079 题意:n个点选面积最大的三角形 代码: 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 const int MAX_N = 100007; 8 9 struct Point { 10 double x, y; 11 Po

poj 2187【旋转卡壳】

求平面最远点对 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; const int N=50005; int n,w=1,top; double ans; struct dian { double x,y; dian(double X=0,double Y=0) { x=X,y=Y; } dian operator + (

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

【POJ 2079】Triangle

Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 8437   Accepted: 2497 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

POJ 3608 两凸包最近距离 旋转卡壳

Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8071   Accepted: 2364   Special Judge Description Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory