题目链接:http://poj.org/problem?id=3301
这个题目刚拿到就向计算几何那里去想,后来又想到二分,想到三分,想了好长时间也没能得出一个有效的结论
后来看了题解明白了意思
这个题目的三分方法比较经典,题目默认正方形的一条边平行X轴,然后让点去旋转,三分枚举点旋转的角度
得出结果,这个题目的逆向思维值得学习。
这是坐标旋转的角度变换公式:
x1=cos(angle)*x-sin(angle)*y;
y1=sin(angle)*x+cos(angle)*y;
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <cmath>
using namespace std;
#define maxn 100
#define inf 1e12
#define eps 1e-8
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)
#define PI acos(-1.0)
struct point{
double x,y;
point(double _x=0,double _y=0):x(_x),y(_y){}
}po[maxn];
int n;
double find_ans(double angle){
double a=-inf,b=inf,c=-inf,d=inf,x,y;
for(int i=0;i<n;i++){
x=cos(angle)*po[i].x-sin(angle)*po[i].y;
y=sin(angle)*po[i].x+cos(angle)*po[i].y;
a=MAX(x,a);
b=MIN(x,b);
c=MAX(y,c);
d=MIN(y,d);
}
return MAX(a-b,c-d);
}
double solve(){
double ans=inf,l=0,r=PI,mid,now,temp;
while(fabs(r-l)>eps){
mid=(l+r)/2;
temp=find_ans(mid);
mid+=eps;
now=find_ans(mid);
mid-=eps;
if(now > temp) r=mid;
else l=mid;
if(ans > temp)
ans=temp;
}
return ans*ans;
}
int main(){
int i,j,k,t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%lf%lf",&po[i].x,&po[i].y);
}
printf("%.2lf\n",solve());
}
return 0;
}