HDU 2202 最大三角形 (凸包)

Description

老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角形拥有的面积最大。

Eddy对这道题目百思不得其解,想不通用什么方法来解决,因此他找到了聪明的你,请你帮他解决这个题目。

Input

输入数据包含多组测试用例,每个测试用例的第一行包含一个整数n,表示一共有n个互不相同的点,接下来的n行每行包含2个整数xi,yi,表示平面上第i个点的x与y坐标。你可以认为:3 <= n <= 50000 而且 -10000 <= xi, yi <= 10000.

Output

对于每一组测试数据,请输出构成的最大的三角形的面积,结果保留两位小数。

每组输出占一行。

Sample Input

3
3 4
2 6
3 7
6
2 6
3 9
2 0
8 0
6 6
7 7

Sample Output

1.50
27.00

数据量过大如果直接暴力枚举三个点面积取最大会超时
因为最大三角形的顶点一定在凸包上,所以可以用graham扫描线求凸包缩小数据量再枚举

graham扫描线法

  1. 取得最左下的点的下标,并把其与第一个位置的点交换
  2. 以第一个点为原点水平线为x轴,进行极角排序(或者说与原点连线的斜率排序)
  3. graham扫描线(栈的思想 不过下面的代码用的是数组)
    • 第一个点和第二个点肯定在凸包上
    • 对后续点进行遍历(设为点 x)
      • 取栈顶两个点连线 l
      • 如果 x在l的右边则把栈顶元素出栈(while循环)
      • x入栈

最后得到的栈中的点集就是凸包的点集

极点排序(叉积)

HDU 2202 最大三角形 (凸包)_第1张图片

三个点构成的三角形面积

叉积是两个向量所构成的平行四边形的有向面积

因为可能会有多次出栈操作,所以用while循环

P3 -> P4 -> P5 -> P6 -> P5出栈 -> P4出栈

HDU 2202 最大三角形 (凸包)_第2张图片

代码

#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define inf 0x3f3f3f3f
#define pi 3.1415926535
using namespace std;
struct node
{
    double x,y;
};
node w[50005],v[50005];
int n,t;
bool cmp(node a,node b)//极角排序(叉积)
{
    if((a.x-w[0].x)*(b.y-w[0].y)-(a.y-w[0].y)*(b.x-w[0].x)==0)
        return a.x0;
}
double cj(node a,node b,node c)//叉积  A=a-c    B=b-c(A和B呈右手系返回值>0左手系<0共线=0)
{
    return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}
void graham()//graham扫描线求凸包
{
    t=1;
    v[0]=w[0],v[1]=w[1];
    for(int i=2; i1&&cj(w[i],v[t],v[t-1])>=0)
            --t;
        v[++t]=w[i];
    }
}
int main()
{
    //freopen("text.txt","r",stdin);
    while(~scanf("%d",&n))
    {
        t=0;
        for(int i=0; i=2)
            printf("%.2f\n",ans/2);
        
    }
}

你可能感兴趣的:(HDU 2202 最大三角形 (凸包))