//题意很简单就是要求N个点的最大三角形的面积。。想到凸包。。一看数据,1000000,,用枚举的话肯定会TLE。。
//花了两天看了旋转卡壳。。现在还是不是很懂。。。
//凸包上的点有可能3点共线啊。。。一个跟屎一样的问题,,搞了我两天。。晕死。。
//下次要学乖了,,,3点共线啊。。晕。。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#define pi acos(-1.0)
using namespace std;
typedef double pointper;//点坐标的类型
#define POINTNUM 100005//最多点的个数
#define PREX 1e-11 //当点坐标为实数型的时候用
struct node
{
pointper x,y;
}Point[100001];
class Polygon
{
public:
int sta[POINTNUM];//在凸包上点的坐标
node point[POINTNUM];
bool flag[POINTNUM];
int top,n,stab;//n为读入的点的个数,top-1为凸包上点的个数,(0~~top-2)是凸包上点的坐标,top-1和0存的都是第一个点;
pointper x1,y1,x2,y2;
polygon()
{
top=n=0;
}
static bool cmp(const node &A,const node &B)
{
return A.x<B.x||A.x==B.x&&A.y<B.y;//先根据X排序,然后根据Y排序
}
bool X(double x1,double y1,double x2,double y2,bool f)//f为true表示求的包括边上的点
{
if(f)
return x1*y2-x2*y1>=0.0||fabs(x1*y2-x2*y1)<PREX;
return x1*y2-x2*y1>0.0;
}
double dis(node a,node b)
{
return sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));
}
double max(double a,double b)
{
return a>b?a:b;
}
double Xmult(node o,node a,node b)
{
return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
void pointselect(bool f);//求凸包上的点,f为true表示求的包括边上的点;
void getpoint(int i,bool f);
void XY(int i);//辅助X()求叉乘
double length();//求凸包的周长
double area();//求凸包的面积;
bool IsInPoly(double x,double y,bool f);
};
Polygon Tubao;
void Polygon::XY(int i)
{
x1=point[i].x-point[sta[top-2]].x;
y1=point[i].y-point[sta[top-2]].y;
x2=point[sta[top-1]].x-point[sta[top-2]].x;
y2=point[sta[top-1]].y-point[sta[top-2]].y;
}
void Polygon::getpoint(int i,bool f)
{
XY(i);
if(top==stab||X(x1,y1,x2,y2,f))
{
sta[top++]=i;
flag[i]=false;
}
else
{
top--;
flag[sta[top]]=true;
XY(i);
while(top>stab&&!X(x1,y1,x2,y2,f))
{
top--;
flag[sta[top]]=true;
XY(i);
}
sta[top++]=i;
flag[i]=false;
}
}
void Polygon::pointselect(bool f)
{
int i;
memset(flag,true,n+1);
sort(point,point+n,cmp);
sta[0]=0;
sta[1]=1;
top=2;
flag[1]=false;
stab=1;
for(i=2;i<n;i++)
getpoint(i,f);
stab=top;
for(i=n-2;i>=0;i--)
if(flag[i])
getpoint(i,f);
}
double Polygon::length()
{
double s=0.0;
int i;
for(i=1;i<top;i++)
s+=sqrt(1.0*(point[sta[i]].x-point[sta[i-1]].x)*(point[sta[i]].x-point[sta[i-1]].x)+(point[sta[i]].y-point[sta[i-1]].y)*(point[sta[i]].y-point[sta[i-1]].y));
return s;
}
double Polygon::area()
{
double s=0.0;
int i;
for(i=1;i<top;i++)
s+=point[sta[i-1]].x*point[sta[i]].y-point[sta[i]].x*point[sta[i-1]].y;
return fabs(s/2);
}
bool Polygon::IsInPoly(double x,double y,bool f)//double型
{
int i;
for(i=1;i<top;i++)
if(!X(x-point[sta[i-1]].x,y-point[sta[i-1]].y,point[sta[i]].x-point[sta[i-1]].x,point[sta[i]].y-point[sta[i-1]].y,f))
return false;
return true;
}
int main()
{
int i,j,k;
while(scanf("%d",&Tubao.n)!=EOF)
{
for(i=0;i<Tubao.n;i++)
{
scanf("%lf %lf",&Tubao.point[i].x,&Tubao.point[i].y);
}
if(Tubao.n==3)//不知道我的凸包的模板为什么处理不了3个点的情况。。
{
double g;
double x1=Tubao.point[0].x-Tubao.point[1].x;
double y1=Tubao.point[0].y-Tubao.point[1].y;
double x2=Tubao.point[0].x-Tubao.point[2].x;
double y2=Tubao.point[0].y-Tubao.point[2].y;
g=fabs((x1*y2-x2*y1)/2.0);
printf("%.2lf\n",g);
}
else
{
Tubao.pointselect(0);//凸包上的点有可能3点共线啊。。。一个跟屎一样的问题,,搞了我两天。。晕死。。
double ans=0,ans1=0;
int n=2;
for(i=0;i<Tubao.top;i++)
{
ans=-1;
n=(i+2)%Tubao.top;
for(j=i+1;j<Tubao.top;j++)
{
while(Tubao.Xmult(Tubao.point[Tubao.sta[i]],Tubao.point[Tubao.sta[j]],Tubao.point[Tubao.sta[n+1]])>Tubao.Xmult(Tubao.point[Tubao.sta[i]],Tubao.point[Tubao.sta[j]],Tubao.point[Tubao.sta[n]]))
n=(n+1)%Tubao.top;
ans=Tubao.max(ans,Tubao.Xmult(Tubao.point[Tubao.sta[i]],Tubao.point[Tubao.sta[j]],Tubao.point[Tubao.sta[n]]));
}
if(ans1<ans)
ans1=ans;
}
printf("%.2lf\n",ans1*0.5);
}
}
return 0;
}
/*
题目大意:输入n个点的坐标,计算其中最大的三角形面积
很显然最大面积的三角形一定在这个点集的凸包上,因此先求出凸包。如果直接枚举凸包同样会超时,可以借助求凸包直径类似的方法来求最大面积的三角形,使用旋转卡壳方法。
枚举三角形的第一个顶点i;
然后初始第二个顶点j=i+1,第三个顶点k=j+1;
循环K+1直到Area(i,j,k)>Area(i,j,k+1),更新最大面积
旋转j,k两个点
(1) 如果Area(i,j,k)<Area(i,j,k+1)且k!=i,则k=k+1,否则2
(2) 更新面积j=j+1,如果j=I,跳出循环
这样旋转一周,求得的面积就是以i为顶点的最大三角形面积。
#define N 50005
#define max(a,b) a>b?a:b
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
int x,y;
}dd[N];
int n,stak[N],top,top1;
bool cmp(node a,node b)
{
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
bool judge_right(int o,int a,int b)
{
int ax=dd[a].x-dd[o].x;
int bx=dd[b].x-dd[o].x;
int ay=dd[a].y-dd[o].y;
int by=dd[b].y-dd[o].y;
return (__int64)bx*ay>(__int64)ax*by;
}
double area(int o,int a,int b)
{
int ax=dd[a].x-dd[o].x;
int bx=dd[b].x-dd[o].x;
int ay=dd[a].y-dd[o].y;
int by=dd[b].y-dd[o].y;
return abs(bx*ay-ax*by)*1.0/2.0;
}
void build_map()
{
int i;
top=0;
sort(dd,dd+n,cmp);
stak[top++]=0;
stak[top++]=1;
for(i=2;i<n;i++)
{
stak[top++]=i;
while(top>=3)
{
if(judge_right(stak[top-3],stak[top-2],stak[top-1]))
break;
stak[top-2]=stak[top-1];
top--;
}
}
top1=top;
stak[top++]=n-2;
for(i=n-3;i>=0;i--)
{
stak[top++]=i;
while(top-top1>=2)
{
if(judge_right(stak[top-3],stak[top-2],stak[top-1]))
break;
stak[top-2]=stak[top-1];
top--;
}
}
top--;
}
int main()
{
int i,j,k;
while(scanf("%d",&n),n!=-1)
{
for(i=0;i<n;i++)
scanf("%d%d",&dd[i].x,&dd[i].y);
build_map();
double ans=0;
for(i=0;i<top;i++)
{
j=(i+1)%top;
k=(j+1)%top;
while(k!=i&&area(stak[i],stak[j],stak[k])<area(stak[i],stak[j],stak[(k+1)%top]))
k=(k+1)%top;
if(k==i)
continue;
int kk=(k+1)%top;
while(j!=kk&&k!=i)
{
ans=max(ans,area(stak[i],stak[j],stak[k]));
while(k!=i&&area(stak[i],stak[j],stak[k])<area(stak[i],stak[j],stak[(k+1)%top]))
k=(k+1)%top;
j=(j+1)%top;
}
}
printf("%.2lf\n",ans);
}
return 0;
}
*/