农田开发
时间限制(普通/Java)
:
1000 MS/ 3000 MS 运行内存限制 : 65536 KByte
总提交 : 36 测试通过 : 24
总提交 : 36 测试通过 : 24
题目描述
有一块农田,田地里安放上N个小木桩,木桩的占地面积忽略不计。选择三个小木桩,使得三个小木桩的围成的三角形占地面积最大。
输入
第一行一个整数N(3<=n<=100),便是木桩个数。
接下来N行,每行含有两个整数xi和yi(-10000<=xi,yi<=10000),表示第i个木桩的平面坐标。
输出
仅含有一个数,表示得到的农田面积的最大值,结果保留一位小数。
样例输入
4
0 0
0 1
1 0
1 1
样例输出
0.5
实现代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int N=50005;
struct Point
{
double x,y;
};
Point stack[N];
Point p[N];
Point MinA;
int top;
double dist(Point A,Point B)
{
return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
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);
}
bool cmp(Point a,Point b)
{
double k=cross(MinA,a,b);
if(k>0) return 1;
if(k<0) return 0;
return dist(MinA,a)<dist(MinA,b);
}
void Graham(int n)
{
int i;
for(i=1; i<n; i++)
if(p[i].y<p[0].y||(p[i].y==p[0].y&&p[i].x<p[0].x))
swap(p[i],p[0]);
MinA=p[0];
sort(p+1,p+n,cmp);
stack[0]=p[0];
stack[1]=p[1];
top=1;
for(i=2; i<n; i++)
{
while(cross(stack[top-1],stack[top],p[i])<=0&&top>=1) --top;
stack[++top]=p[i];
}
}
double rotating_calipers(int n)
{
int j=1,k=0;
double ans=0;
for(int i=0;i<n;i++)
{
j=(i+1)%n;
k=(j+1)%n;
while(fabs(cross(stack[i],stack[j],stack[k]))<fabs(cross(stack[i],stack[j],stack[(k+1)%n])))
k=(k+1)%n;
while(j!=i&&k!=i)
{
ans=max(ans,fabs(cross(stack[i],stack[j],stack[k])));
while(fabs(cross(stack[i],stack[j],stack[k]))<fabs(cross(stack[i],stack[j],stack[(k+1)%n])))
k=(k+1)%n;
j=(j+1)%n;
}
}
return ans*0.5;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==-1) break;
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
if(n<3)
{
puts("0.00");
continue;
}
Graham(n);
top++;
if(top<3)
{
puts("0.0");
continue;
}
if(top==3)
{
printf("%.1lf\n",fabs(cross(stack[0],stack[1],stack[2]))/2);
continue;
}
printf("%.1lf\n",rotating_calipers(top));
}
return 0;
}