Description
在二维坐标系中给出一些点,求能覆盖他们的最小正方形的面积(正方形的边可以不平行坐标轴)
Input
第一行一个整数T表示用例组数,每组用例第一行为一整数n表示点数,之后n行每行两个整数x,y表示该点横纵坐标(T<=30,n<=30,|x|,|y|<=500)
Output
对于每组用例,输出覆盖这n个点的正方形最小面积
Sample Input
2
4
-1 -1
1 -1
1 1
-1 1
4
10 1
10 -1
-10 1
-10 -1
Sample Output
4.00
242.00
Solution
不让正方形旋转,而是让正方形边与坐标轴平行,让点旋转,三分点的旋转角度,范围[0,pi],每次旋转后统计横纵坐标最大差值,取个最大值即为当前角度对应的正方形边长
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define eps 1e-12
#define pi acos(-1.0)
#define maxn 33
struct node
{
double x,y;
node spin(double a)
{
node ans;
ans.x=x*sin(a)-y*cos(a);
ans.y=x*cos(a)+y*sin(a);
return ans;
}
}a[maxn],b[maxn];
int T,n;
double cal(double x)
{
for(int i=0;i<n;i++)b[i]=a[i].spin(x);
double x1,x2,y1,y2;
x1=x2=b[0].x,y1=y2=b[0].y;
for(int i=1;i<n;i++)
x1=min(x1,b[i].x),x2=max(x2,b[i].x),y1=min(y1,b[i].y),y2=max(y2,b[i].y);
return max(x2-x1,y2-y1);
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
double l=0,r=pi,mid1,mid2,f1,f2;
while(1)
{
mid1=(l+r)/2,mid2=(mid1+r)/2;
f1=cal(mid1),f2=cal(mid2);
if(abs(f1-f2)<eps)break;
else if(f1<f2)r=mid2;
else l=mid1;
}
printf("%.2f\n",f1*f1);
}
return 0;
}