[POJ3301]Texas Trip(三分-最小正方形覆蓋)
阿新 • • 發佈:2019-02-07
題目:
題解:
設正方形的邊都與座標軸平行可以求出來一個正方形
如果這個正方形旋轉一個角度的話正方形的大小可能會改變
經過我多年文化課做幾何旋轉題目,可以發現正方形的面積關於旋轉角度的函式單峰
如果面積隨角度變化是單峰的函式,那麼自然就可以想到是三分,按照題目要求求正方形最小的面積,如果正方形是平行於x軸的,那麼正方形面積是x的最大距離*y的最大的距離。然後旋轉正方形,在0到90度內總會找到一個正方形面積的最小值
但是旋轉正方形比較麻煩,我們可以考慮旋轉座標系,將座標系旋轉0~90度 ,按旋轉的角度重新計算各點的座標,然後找出x的差和y的差,計算面積。
因為是單峰的函式,所以用三分角度,找到一個最小的面積。
注意:三分的eps要很小,1e-12
角度旋轉公式x = x*cos(j) - y*sin(j) ; y = x*sin(j) + y*cos(j)
程式碼:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
double eps=1e-12;
const int N=50;
#define INF 1e9
const double pi=acos(-1.0);
struct po{double x,y;}a[N];
double maxx,maxy,minx,miny;int n;
double bc(double j)
{
double x,y;
maxx=maxy=-INF;
minx=miny=INF;
for (int i=1;i<=n;i++)
{
x=a[i].x*cos(j)-a[i].y*sin(j);
y=a[i].x*sin(j)+a[i].y*cos(j);
maxx=max(maxx,x);
minx=min(minx,x);
maxy=max(maxy,y);
miny=min(miny,y);
}
return max(maxx-minx,maxy-miny);
}
int main()
{
int T;scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
double l=0,r=pi/2,m1,m2;
while (r-l>=eps)
{
m1=l+(r-l)/3;
m2=r-(r-l)/3;
if (bc(m1)<bc(m2)) r=m2;
else l=m1;
}
l=bc(l);
printf("%.2lf\n",l*l);
}
}