题意:给出最多30个点的坐标,求覆盖所有点的最小正方形面积。
解法:没有证明正确性,网上对于此法的正确性有争议。反正是用三分过的,也许数据弱了。就是在0-90度的旋转范围内三分角度(所有点旋转的角度)。正方形的边总是平行于坐标轴的,那么每次正方形的边长总是最大x坐标之差和最大y坐标之差中更大那个。
点旋转A后的坐标公式
X1=cos(A)*X0 - sin(A)*Y0;
Y1=sin(A)*X0 + cos(A)*Y0;
代码:
/****************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
using namespace std;
#define sz(c) ((int)(c).size())
#define forl(i, a, b) for(int i = (a); i < (b); ++i)
#define forle(i, a, b) for(int i = (a); i <= (b); ++i)
#define repc(n) for(int repp_b = (n), repp = 0; repp < repp_b; ++repp)
#define rst(a, v) memset(a, v, sizeof a)
#define eps 1e-8
#define INF (1<<29)
#define LL __int64
inline int rdi() { int d; scanf("%d", &d); return d; }
inline char rdc() { scanf(" "); return getchar(); }
inline void rds(char *s) {scanf("%s", s); }
inline double rddb() { double d; scanf("%lf", &d); return d; }
struct point
{
double x,y;
} points[50];
int n;
double make(double angle)
{
double maxx=-10000,minx=10000,maxy=-10000,miny=10000;
forl(i,0,n)
{
point p;
p.x=points[i].x*cos(angle)-sin(angle)*points[i].y;
p.y=points[i].x*sin(angle)+cos(angle)*points[i].y;
maxx=max(maxx,p.x);
minx=min(minx,p.x);
maxy=max(maxy,p.y);
miny=min(miny,p.y);
}
return max(maxx-minx,maxy-miny);
}
int main()
{
repc(rdi()){
n=rdi();
forl(i,0,n){
points[i].x=rddb(),points[i].y=rddb();//cout<<points[i].y<<endl;
}
double left=0,right=acos(-1)/2;
while(right-left>=0.00000001)
{
//cout<<left<<endl;
double middle=(left+right)/2;
double middleagain=(middle+right)/2;
if(make(middle)<make(middleagain))
right=middleagain;
else
left=middle;
}
printf("%.2f\n",make(left)*make(left));
}
return 0;
}