您的位置:首页 > 其它

求点集中面积最大的三角形

2013-02-25 18:39 381 查看
如果枚举3个点再算面积,必然超时。

很显然的最大面积的三角形的三个顶点必然是这个点集的凸包上的点,因此先求出凸包。

如果求出凸包仍然枚举,一样会超时。

这个可以借助求凸包直径类似的方法来求最大面积的三角形,使用旋转卡壳方法。

枚举三角形的第一个顶点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)

(2)更新面积,j=j+1,如果j=i,跳出循环

这样旋转一圈后,求得的面积就是以i为顶点的最大三角形的面积了。

时间复杂度是O(n^2)

//author:chenkun

//旋转卡壳!

#include <cstdio>

#include <cmath>



const int MAXN=50000;



struct point {

int x,
y;

} p[MAXN+1],h[MAXN+1];



double distance(const point& p1,const
point& p2) {

return sqrt( (p1.x - p2.x) *
(p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));

}



double multiply(const point& sp,const
point& ep,const point& op) {


return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));

}



int partition(point a[],int p,int r) {

int
i=p,j=r+1,k;

double
ang,dis;

point
R,S;


k=(p+r)/2;


R=a[p];


a[p]=a[k];


a[k]=R;


R=a[p];


dis=distance(R,a[0]);

while(1)
{


while(1) {


++i;


if(i>r) {


i=r;


break;


}


ang=multiply(R,a[i],a[0]);


if(ang>0)


break;


else if(ang==0) {


if(distance(a[i],a[0])>dis)


break;


}


}


while(1) {


--j;


if(j<p) {


j=p;


break;


}


ang=multiply(R,a[j],a[0]);


if(ang<0)


break;


else if(ang==0) {


if(distance(a[j],a[0])<dis)


break;


}


}


if(i>=j)break;


S=a[i];


a[i]=a[j];


a[j]=S;

}


a[p]=a[j];


a[j]=R;

return
j;

}



void anglesort(point a[],int p,int r) {

if(p<r) {


int q=partition(a,p,r);


anglesort(a,p,q-1);


anglesort(a,q+1,r);

}

}



//对PointSet求凸包,点数为n,凸包上的点保存在ch中,点数位len

void Graham_scan(point PointSet[],point ch[],int n,int
&len) {

int
i,k=0,top=2;

point
tmp;


for(i=1;i<n;i++)


if ( PointSet[i].x<pointSet[k].x ||


(PointSet[i].x==PointSet[k].x) &&
(PointSet[i].y<pointSet[k].y) )


k=i;


tmp=PointSet[0];


PointSet[0]=PointSet[k];


PointSet[k]=tmp;


anglesort(PointSet,1,n-1);


if(n<3) {


len=n;


for(int i=0;i<n;i++) ch[i]=PointSet[i];


return ;

}


ch[0]=PointSet[0];


ch[1]=PointSet[1];


ch[2]=PointSet[2];

for
(i=3;i<n;i++) {


while (multiply(PointSet[i],ch[top],ch[top-1])>=0)
top--;


ch[++top]=PointSet[i];

}


len=top+1;

}



double Area(int i,int j,int k) {

return
multiply(h[j],h[k],h[i])/2;

}



inline double max(double a,double b){return
a>b?a:b;}

int main() {

int n;


while(scanf("%d",&n)!=EOF&&n!=-1)
{


for(int i=0;i<n;i++)


scanf("%d
%d",&p[i].x,&p[i].y);


int len;


Graham_scan(p,h,n,len);


//for(int i=0;i<len;i++)


// printf("%d
%d\n",h[i].x,h[i].y);




double ans=0;


for(int i=0;i<len;i++) {


int j=(i+1)%len;


int k=(j+1)%len;


while(k!=i&&Area(i,j,k)<area(i,j,(k+1)%len))
{


k=(k+1)%len;


}


if(k==i) continue;


int kk=(k+1)%len;


while(j!=kk&&k!=i) {


ans=max(ans,Area(i,j,k));


while(k!=i&&Area(i,j,k)<area(i,j,(k+1)%len))
{


k=(k+1)%len;


}


j=(j+1)%len;


}


}




printf("%.2f\n",ans);

}

return
0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: