POJ - 2079:Triangle (旋转卡壳,求最大三角形)

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

题意:在二维平面上面找三个点构成三角形,使得其面积最大。

思路1:枚举三角形的一条边,然后通过旋转卡壳找最远的点;

自己想的,而且AC了,但是不够严谨。比如这组样例就过不了:

9 
4752 4262 
3383 413 
759 2927 
4745 4322 
1213 691 
2506 4423 
3040 4460 
1000 1000 
5000 1000 
the correct output is: 
6920000.00 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define RC rotating_calipers
using namespace std;
const int maxn=100010;
struct point{
    double x,y;
    point(double x=0,double y=0):x(x),y(y){}
    bool operator < (const point &c) const { return x<c.x||(x==c.x&&y<c.y);}
    point operator - (const point &c) const { return point(x-c.x,y-c.y);}
    double operator * (const point &c) const { return x*c.y-y*c.x; }
    double operator | (const point &c) const { return (x-c.x)*(x-c.x)+(y-c.y)*(y-c.y); }
};
double det(point A,point B){ return A.x*B.y-A.y*B.x;}
double det(point O,point A,point B){ return det(A-O,B-O);}
point a[maxn],ch[maxn];
void convexhull(int n,int &top)
{
    sort(a+1,a+n+1); top=0;
    for(int i=1;i<=n;i++){
        while(top>1&&det(ch[top-1],ch[top],a[i])<=0) top--;
        ch[++top]=a[i];
    }
    int ttop=top;
    for(int i=n-1;i>=1;i--){
        while(top>ttop&&det(ch[top-1],ch[top],a[i])<=0) top--;
        ch[++top]=a[i];
    }
}
double rotating_calipers(point p[],int top)
{
    double ans=0; int now;
    rep(i,1,top-1){
        int now=i+1;
        rep(j,i,top-1){
           while(fabs(det(p[i],p[j+1],p[now]))<fabs(det(p[i],p[j+1],p[now+1]))){
              now++;
              if(now==top) now=1;
           }
           ans=max(ans,fabs(det(p[i],p[j],p[now])));
        }
    }
    return ans;
}
int main()
{
    int N;
    while(~scanf("%d",&N)&&N!=-1){
        for(int i=1;i<=N;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
        int top; convexhull(N,top);
        double ans=RC(ch,top);
        printf("%.2f\n",0.5*ans);
    }
    return 0;
}
View Code

思路2:枚举三角形的一个点,然后通过旋转卡壳找最远的边。虽然不知道为什么一个对一个错。

单至少发现了免得板子出问题。后面再来解决这个问题。真正的AC代码:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define RC rotating_calipers
using namespace std;
const int maxn=100010;
struct point{
    double x,y;
    point(double x=0,double y=0):x(x),y(y){}
    bool operator < (const point &c) const { return x<c.x||(x==c.x&&y<c.y);}
    point operator - (const point &c) const { return point(x-c.x,y-c.y);}
    double operator * (const point &c) const { return x*c.y-y*c.x; }
    double operator | (const point &c) const { return (x-c.x)*(x-c.x)+(y-c.y)*(y-c.y); }
};
double det(point A,point B){ return A.x*B.y-A.y*B.x;}
double det(point O,point A,point B){ return det(A-O,B-O);}
point a[maxn],ch[maxn];
void convexhull(int n,int &top)
{
    sort(a+1,a+n+1); top=0;
    for(int i=1;i<=n;i++){
        while(top>1&&det(ch[top-1],ch[top],a[i])<=0) top--;
        ch[++top]=a[i];
    }
    int ttop=top;
    for(int i=n-1;i>=1;i--){
        while(top>ttop&&det(ch[top-1],ch[top],a[i])<=0) top--;
        ch[++top]=a[i];
    }
}
double rotating_calipers(point p[],int top)
{
    double ans=0; int now;
    rep(i,1,top-1){
        int now=i+1;
        rep(j,i,top-1){
           while(det(p[i],p[j+1],p[now])<det(p[i],p[j+1],p[now+1])){
              now++;
              if(now==top) now=1;
           }
           ans=max(ans,det(p[i],p[j],p[now]));
        }
    }
    return ans;
}
int main()
{
    int N;
    while(~scanf("%d",&N)&&N!=-1){
        for(int i=1;i<=N;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
        int top; convexhull(N,top);
        double ans=RC(ch,top);
        printf("%.2f\n",0.5*ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hua-dong/p/9620486.html