- 题意:给定一些点,找出包含这些点的最小的正方形。
- 分析:首先在标准坐标系中,确定一个边平行于坐标轴的正方形。然后旋转坐标轴,在(0,π/2)区间内旋转,每次确定的正方形面积是凹函数,找出其中面积最小的正方形即可。
注意:坐标旋转公式
- 代码
#include "bits/stdc++.h"
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mk make_pair
typedef long long ll;
const int maxn = 1e3 + 7;
const int INF = 1e6;
const double EPS = 1e-12;
const double PI = acos(-1.0);
int t,n;
int x[maxn],y[maxn];
double func(double t){
double x1,y1;
double minx, miny;
double maxx, maxy;
minx = miny = INF; maxx = maxy = -INF;
for (int i = 0; i < n; i++) {
x1 = x[i] * cos(t) - y[i] * sin(t);
y1 = y[i] * cos(t) + x[i] * sin(t);
minx = min(x1,minx);
miny = min(y1,miny);
maxx = max(x1,maxx);
maxy = max(y1,maxy);
}
double l = max(maxx - minx,maxy - miny);
return pow(l,2);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>t;
while (t--) {
cin>>n;
for (int i = 0; i < n; i++) {
cin>>x[i]>>y[i];
}
double l = 0, r = PI/2;
while (r - l > EPS) {
double midl = l + (r - l)/3;
double midr = r - (r - l)/3;
if (func(midl) > func(midr)) {
l = midl;
}else r = midr;
}
printf("%.2lf\n",func(r));
}
return 0;
}
- 遇到的问题:
(1)首先是cin的问题,HDU 4355,虽然cin.tie 以及 sync_with_stdio,但依旧TLE,此题数据较小,所以不用scanf也可。
(2)然后是EPS的问题,三分的EPS要小,此题开始我将EPS设置为1e-4,结果WA了,看了别人的题解发现都设置到1e-12。不过我明白了三分的EPS一定要小!
(3)然后是PI的问题,每次我都设置为3.14,一直忘记可以设置为 acos(-1).此后要牢记。