大意:给N个点,用最小面积的正方形覆盖。
三分坐标轴旋转角度,然后在N个点中找最大边长。
坐标偏转后的点的变化公式可用极坐标方程证明。
#include<cstdio>
#include<cmath>
#include<algorithm>
#define maxl 301
#define eps 1e-8
#define inf 2000000001
using namespace std;
int n,t;
const double pi=acos(-1.0);
struct node
{
double x,y;
}a[maxl];
/*
记原点为O
设ρ=OA=√x02+y02
三角换元x0=ρcosθ,y0=ρsinθ
其中cosθ=x0/ρ,sinθ=y0/ρ
逆时针旋转n度后
x=ρcos(θ+n)=ρ(cosθcosn-sinθsinn)=x0cosn-y0sinn
同理y=ρsin(θ+n)=…=x0sinn+y0cosn*/
double calc(double ang)
{
double maxx=-inf,maxy=-inf,minx=inf,miny=inf;
double tx,ty;
for(int i=1;i<=n;i++)
{
tx=a[i].x*cos(ang)-a[i].y*sin(ang);
ty=a[i].y*cos(ang)+a[i].x*sin(ang);
maxx=max(maxx,tx);maxy=max(maxy,ty);
minx=min(minx,tx);miny=min(miny,ty);
}
return max(maxx-minx,maxy-miny);
}
int main()
{
double l,r,mid,midmid,t1,t2;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
scanf("%d",&n);
for(int j=1;j<=n;j++)
scanf("%lf%lf",&a[j].x,&a[j].y);
l=0;r=pi;
while(l+eps<r)
{
mid=(l+r)/2.0;
midmid=(r+mid)/2.0;
t1=calc(mid);
t2=calc(midmid);
if(t1<t2)
r=midmid;
else
l=mid;
}
printf("%.2f\n",t1*t1);
}
return 0;
}