| Time Limit: 3000MS | Memory Limit: 30000K | |
| Total Submissions: 8437 | Accepted: 2497 |
Description
Input
Output
Sample Input
3 3 4 2 6 2 7 5 2 6 3 9 2 0 8 0 6 5 -1
Sample Output
0.50 27.00
Source
旋转卡壳求凸包上的最大三角形面积。
只要把旋转卡壳变形一下:
之前的旋转卡壳是求一个点及其相邻点的对踵点,现在求一个点的时候枚举其他每一个点和这个点的对踵点即可。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define eps 1e-9
using namespace std;
struct Point
{
double x,y;
}a[50005];
int n,tail,h[50005];
bool cmp(Point a,Point b)
{
if (a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
double Cross(Point a,Point b,Point c)
{
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
void Graham()
{
sort(a+1,a+1+n,cmp);
tail=0;
for (int i=1;i<=n;i++)
{
while (tail>=2&&Cross(a[h[tail-2]],a[h[tail-1]],a[i])<eps)
tail--;
h[tail++]=i;
}
int tmp=tail;
h[tail++]=n-1;
for (int i=n-2;i;i--)
{
while (tail>tmp&&Cross(a[h[tail-2]],a[h[tail-1]],a[i])<eps)
tail--;
h[tail++]=i;
}
tail--;
}
double Rotating_calipers()
{
double ans=0.0;
for (int i=0;i<tail;i++)
{
int x=i+1;
for (int j=i+1;j<=tail;j++)
{
while (fabs(Cross(a[h[i]],a[h[j]],a[h[x+1]]))>fabs(Cross(a[h[i]],a[h[j]],a[h[x]])))
x=(x+1)%tail;
ans=max(ans,fabs(Cross(a[h[i]],a[h[j]],a[h[x]])));
}
}
return ans/2.000;
}
int main()
{
while (scanf("%d",&n)!=EOF)
{
if (n==-1) break;
for (int i=1;i<=n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
Graham();
printf("%.2lf\n",Rotating_calipers());
}
return 0;
}
原文地址:http://blog.csdn.net/regina8023/article/details/43899535