http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=40259
题意 给n个点,求出面积最大的三角形面积
显然 三点落在凸包上。nlogn找凸包。
然后 可以证明凸包上的点不超过 sqrt(m),m为坐标系范围,m=1e4
所以可以用sqrt(m)*sqrt(m)的方法枚举两个点,然后旋转卡壳 osqrt(m) 遍历三角形得到答案
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <map> #include <set> #include <vector> #include <iostream> using namespace std; const double pi=acos(-1.0); double eps=1e-8; struct POINT { double x; double y; POINT(double a=0, double b=0) { x=a; //constructor y=b; } }; struct LINESEG { POINT s; POINT e; LINESEG(POINT a, POINT b) { s=a; e=b; } LINESEG() { } }; struct LINE // 直线的解析方程 a*x+b*y+c=0 为统一表示,约定 a >= 0 { double a; double b; double c; LINE(double d1=1, double d2=-1, double d3=0) { a=d1; b=d2; c=d3; } }; double multiply(POINT sp,POINT ep,POINT op) { return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y)); } double dist(POINT p1,POINT p2) // 返回两点之间欧氏距离 { return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) ); } POINT p[50005]; POINT ans[50005]; bool cmp(const POINT& a,const POINT& b)//P[0]指PointSet { if ( multiply(a,b,p[0])>0 || // 极角更小 (multiply(a,b,p[0])==0) && //极角相等,距离更短 dist(p[0],a)<dist(p[0],b) ) return true; else return false; } void Graham_scan(POINT PointSet[],POINT ch[],int n,int &len) //求凸包顶点集 { int i,j,k=0,top=1; POINT tmp; // 选取PointSet中y坐标最小的点PointSet[k],如果这样的点有多个,则取最左边的一个 for(i=1; i<n; i++) if ( PointSet[i].y<PointSet[k].y || (PointSet[i].y==PointSet[k].y) && (PointSet[i].x<PointSet[k].x) ) k=i; tmp=PointSet[0]; PointSet[0]=PointSet[k]; PointSet[k]=tmp; // 现在PointSet中y坐标最小的点在PointSet[0] sort(PointSet+1,PointSet+n,cmp); ch[0]=PointSet[0]; ch[1]=PointSet[1]; for (i=2; i<n; i++) { while (top>0 &&multiply(PointSet[i],ch[top],ch[top-1])>=0) top--; ch[++top]=PointSet[i]; } len=top+1; } double ptoldist(POINT p,LINESEG l) { return abs(multiply(p,l.e,l.s))/dist(l.s,l.e); } double rotating_calipers(POINT *ch,int n) { ch[n]=ch[0]; double ans=-1; for (int i=0; i<n; i++) { int q=(i+2)%n; for(int p=(i+1)%n; (p+1)%n!=i ; p=(p+1)%n) { double tmp=-1; while (1) { double tmp2=ptoldist(ch[q],LINESEG(ch[p],ch[i])); if (tmp2>tmp) { tmp=tmp2; q++; if (q==n) q=0; } else { q--;if (!q) q=n-1; break;} } ans=max(ans,tmp*dist(ch[p],ch[i])/2); } } return ans; } int main() { int i,j; int n; while (scanf("%d",&n)!=EOF && n!=-1) { for (i=0; i<n; i++) { scanf("%lf%lf",&p[i].x,&p[i].y); } int len=-1; Graham_scan(p,ans,n,len); printf("%.2lf\n",rotating_calipers(ans,len)); } return 0; }