一开始参照书上的写法些了一个,后来理解了一下自己写了一个
自写的:
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
#define MAXN 50005
struct Point
{
int x, y;
bool operator < (const Point& _P) const
{
return y<_P.y||(y==_P.y&&x<_P.x);
};
}point[MAXN],stack[MAXN];
int cross(Point a,Point b,Point o)
{
return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
}
double area(Point o,Point a,Point b)
{
int ax=a.x-o.x;
int bx=b.x-o.x;
int ay=a.y-o.y;
int by=b.y-o.y;
return abs(bx*ay-ax*by)*1.0/2.0;
}
//graham()求凸包
void convex_hull(Point *p,Point *stack,int n,int &len)
{
sort(p, p+n);
stack[0]=p[0];
stack[1]=p[1];
int top=1;
for(int i=2;i<n;i++)
{
while(top>0&&cross(stack[top],p[i],stack[top-1])<=0)
top--;
stack[++top]=p[i];
}
int tmp=top;
for(int i=n-2;i>=0;i--)
{
while(top>tmp&&cross(stack[top],p[i],stack[top-1])<=0)
top--;
stack[++top]=p[i];
}
len=top;
}
int dist(Point a,Point b)
{
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
//旋转卡壳
double rotating_calipers(Point *stack,int n)
{
int q=1;
double ans=0;
stack[n]=stack[0];
/* for(int z=0;z<n;z++)
cout<<stack[z].x<<" "<<stack[z].y<<endl;
system("pause");*/
for(int p=0;p<n;p++)
{
int j=(p+1)%n;
int k=(j+1)%n;
//卡壳确定两个点求面积,而求距离就只用确定一个点只用一个while
while(area(stack[p],stack[j],stack[k])<area(stack[p],stack[j],stack[(k+1)%n]))
k=(k+1)%n;
if(k==p)continue;
int kk=(k+1)%n;
while(j!=kk && k!=p)
{
ans=max(ans,area(stack[p],stack[j],stack[k]));
while(k!=p && area(stack[p],stack[j],stack[k])<area(stack[p],stack[j],stack[(k+1)%n]))
k=(k+1)%n;
j=(j+1)%n;
}
}
return ans;
}
int main()
{
int n, len;
while(scanf("%d",&n)!=EOF && n!=-1)
{
for(int i = 0;i < n;i++)
{
scanf("%d %d",&point[i].x,&point[i].y);
}
convex_hull(point,stack,n,len);
printf("%.2lf\n",rotating_calipers(stack,len));
}
return 0;
}
书上的介绍
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 50005
using namespace std;
struct node
{
int x,y;
}dd[N];
int n,stak[N],top,top1;
bool cmp(const node &a,const 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)!=EOF && n!=-1)
{
for(i=0;i<n;i++)
scanf("%d%d",&dd[i].x,&dd[i].y);
build_map();
double ans=0;
/*for(int i=0;i<top;i++)
cout<<dd[stak[i]].x<<" "<<dd[stak[i]].y<<endl;*/
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);
}
}