POJ 3301 Texas Trip (三分)
ACM
题目地址:
POJ 3301 Texas Trip
题意:
给定二维平面的n个点,要求一个面积最小的正方形,使其能覆盖全部的点。
分析:
去求凸包你就输了...
我们能够让正方形不要动。全部点进行旋转变换。这样结果是不会变形的。
变形即: x1=x*cos(a)-y*sin(a); y1=x*sin(a)+y*cos(a)
本来想暴力看看的,后来发现是三分的,证明引用巨巨的:
能够证明它们都是凸性函数。故他们差的最大值也是凸性函数,故能够用三分法,对旋转角度进行三分。求出最小的满足要求的正方形,具体过程见代码。
交了几发,再次验证了:g++的double输出默认是用%f的。
代码:
/*
* Author: illuz <iilluzen[at]gmail.com>
* File: 3301.cpp
* Create Date: 2014-09-18 09:25:04
* Descripton: triple
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;
const int N = 31;
const double PI = acos(-1.0);
const double EPS = 1e-12;
int t, n;
double x[N], y[N];
inline double calc(double a) {
double minx = 1000, miny = 1000, maxx = -1000, maxy = -1000;
double xx, yy;
repf (i, 1, n) {
xx = x[i] * cos(a) - y[i] * sin(a);
yy = x[i] * sin(a) + y[i] * cos(a);
minx = min(minx, xx);
maxx = max(maxx, xx);
miny = min(miny, yy);
maxy = max(maxy, yy);
}
return max(maxx - minx, maxy - miny);
}
int main() {
ios_base::sync_with_stdio(0);
double l, r, mid, mmid, ans;
cin >> t;
while (t--) {
cin >> n;
repf (i, 1, n) {
cin >> x[i] >> y[i];
}
l = 0.0;
r = PI;
while (r - l > EPS) {
mid = (l + r) / 2;
mmid = (mid + r) / 2;
ans = calc(mid);
if (ans <= calc(mmid))
r = mmid;
else
l = mid;
}
printf("%.2f\n", ans * ans);
// brute force
// ans = 1000;
// for (double i = 0.0; i <= PI; i += 0.00005)
// ans = min(ans, calc(i));
// printf("%.2lf\n", ans * ans);
}
return 0;
}