HDU 2202 最大三角形(凸包)
Problem Description
老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角形拥有的面积最大。
Eddy对这道题目百思不得其解,想不通用什么方法来解决,因此他找到了聪明的你,请你帮他解决这个题目。
Eddy对这道题目百思不得其解,想不通用什么方法来解决,因此他找到了聪明的你,请你帮他解决这个题目。
Input
输入数据包含多组测试用例,每个测试用例的第一行包含一个整数n,表示一共有n个互不相同的点,接下来的n行每行包含2个整数xi,yi,表示平面上第i个点的x与y坐标。你可以认为:3 <= n <= 50000 而且 -10000 <= xi, yi <= 10000.
Output
对于每一组测试数据,请输出构成的最大的三角形的面积,结果保留两位小数。
每组输出占一行。
每组输出占一行。
Sample
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
题意:
求最大的三角形面积。
思路:
做出凸包,遍历即可,主要是旋转卡壳不会用,恰好后台数据没有那么大N^3没有T。三角形面积可以用两向量叉乘/2求出。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define PI 3.1415926535 using namespace std; struct node { int x,y; }; node vex[100000];//存入的所有的点 node stackk[100000];//凸包中所有的点 int xx,yy; bool cmp1(node a,node b) { if(a.y==b.y) return a.x<b.x; else return a.y<b.y; } double cross(node a,node b,node c)//计算叉积 { return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } double dis(node a,node b)//计算距离 { return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y)); } bool cmp2(node a,node b)//极角排序另一种方法,速度快 { if(atan2(a.y-yy,a.x-xx)!=atan2(b.y-yy,b.x-xx)) return (atan2(a.y-yy,a.x-xx))<(atan2(b.y-yy,b.x-xx)); return a.x<b.x; } bool cmp(node a,node b)//极角排序 { int m=cross(vex[0],a,b); if(m>0) return 1; else if(m==0&&dis(vex[0],a)-dis(vex[0],b)<=0) return 1; else return 0; /*if(m==0) return dis(vex[0],a)-dis(vex[0],b)<=0?true:false; else return m>0?true:false;*/ } int main() { int t,L; while(~scanf("%d",&t)) { int i; for(i=0; i<t; i++) { scanf("%d%d",&vex[i].x,&vex[i].y); } memset(stackk,0,sizeof(stackk)); sort(vex,vex+t,cmp1); stackk[0]=vex[0]; xx=stackk[0].x; yy=stackk[0].y; sort(vex+1,vex+t,cmp2); stackk[1]=vex[1];//将凸包中的前两个点存入凸包的结构体中 int top=1;//最后凸包中拥有点的个数*/ for(i=2; i<t; i++) { while(i>=1&&cross(stackk[top-1],stackk[top],vex[i])<0) top--; stackk[++top]=vex[i]; } double s=0;//三角形的面积可以由向量叉乘/2 for(int i = 0; i<=top; i++) for(int j = i+1; j<=top; j++) for(int k = j+1; k<=top; k++) s = max(s,cross(stackk[i],stackk[j],stackk[k])); printf("%.2lf\n",s/2.0); } }