poj2079(一堆点找出最大的三角形)

7 篇文章 0 订阅
6 篇文章 0 订阅

题意:

给出n个二维坐标点,找出三个点,它们组成的三角形面积最大。


思路:

首先,面积最大的三角形的三个点一定在凸包上,我们先求所有点的凸包,然后选择一个边i、j,枚举k,找到一个最大的面积,然后定下i,枚举j和k,找到最大的面积。

pojG++是坑!


代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<string>

#define EPS 1e-10
#define MAXN 50100

using namespace std;

struct point
{
	double x,y;
	point(){}
	point(double tx,double ty):x(tx),y(ty){}
	point(const point &tt)
	{
		x=tt.x;
		y=tt.y;
	}
};
point data[MAXN];
point convex[MAXN];
point start(0,0);

inline double cross(const point &p1,const point &p2,const point &q1,const point &q2)
{
    return (q2.y-q1.y)*(p2.x-p1.x)-(q2.x-q1.x)*(p2.y-p1.y);    
}

inline bool cmp1(const point &a,const point &b)
{
	if(a.y==b.y)
		return a.x<b.x;
	return a.y<b.y;
}

inline bool cmp2(const point &a,const point &b)//逆时针排序 
{
    point origin;
    origin=start;
    return cross(origin,a,origin,b)>0||(cross(origin,a,origin,b)==0&&fabs(a.x)<fabs(b.x));
}

inline void convex_hull(int &cnt,int n)
{
    sort(data,data+n,cmp1);
    start=data[0];
    sort(data+1,data+n,cmp2);
    convex[cnt++]=start;
    convex[cnt++]=data[1];
    for(int i=2;i<n;++i) 
	{
        while(cnt>=2&&cross(convex[cnt-2],convex[cnt-1],convex[cnt-1],data[i])<=0)
			--cnt;
        convex[cnt++]=data[i];    
    }        
}

inline double rotating_calipers(int n)
{
    int j=1,k=0;
    double area=0;
    for(int i=0;i<n;++i) 
	{
        j=(i+1)%n;
        k=(j+1)%n;
        while(fabs(cross(convex[i],convex[j],convex[i],convex[k]))< 
                    fabs(cross(convex[i],convex[j],convex[i],convex[(k+1)%n])))
            k=(k+1)%n;            
        while(j!=i&&k!=i) 
		{
            area=max(area,fabs(cross(convex[i],convex[j],convex[i],convex[k])));
            while(fabs(cross(convex[i],convex[j],convex[i],convex[k]))<
                         fabs(cross(convex[i],convex[j],convex[i],convex[(k+1)%n])))
                k=(k+1)%n;                    
            j=(j+1)%n;    
        }
    }
    return area;    
}

int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		if(n==-1)
			break;
		for(int i=0;i<n;i++)
			scanf("%lf%lf",&data[i].x,&data[i].y);
		if(n<=2)
		{
			printf("0.00\n");
			continue;
		}
		int cnt=0;
		convex_hull(cnt,n);
		if(cnt<=2)
			printf("0.00\n");
		else
		{
			if(cnt==3)
				printf("%.2lf\n",fabs(cross(convex[0],convex[1],convex[0],convex[2]))/2);
			else 
				printf("%.2lf\n",rotating_calipers(cnt)/2);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值