【bzoj3564】 [SHOI2014]信号增幅仪
题目描述:
无线网络基站在理想状况下有效信号覆盖范围是个圆形。而无线基站的功耗与圆的半径的平方成正比。
现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站....
就在你拿起键盘准备开始敲代码的时候,你的好朋友发明家 SHTSC 突然出现了。SHTSC 刚刚完成了他的新发明——无线信号增幅仪。增幅仪能够在不增加无线基站功耗的前提下,使得有效信号的覆盖范围在某一特定方向上伸长若干倍。即:使用了增幅仪的无线基站覆盖范围是个椭圆,其功耗正比于半短轴长的平方。现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站,并在增幅仪的帮助下使所有的用户都能接收到信号,且无线基站的功耗最小。
注意:由于SHTSC 增幅仪的工作原理依赖地磁场,增幅的方向是恒定的。
输入:
第一行一个整数:n。平面内的用户个数。
之后的 n 行每行两个整数 x, y,表示一个用户的位置。
第 n+2 行一个整数:a。表示增幅仪的增幅方向,单位是度。表示增幅仪的方向是从 x 正方向逆时针转 a 度。
第 n+3 行一个整数:p。表示增幅仪的放大倍数。
输出:
输出一行一个实数,为能够覆盖所有用户的最小椭圆的半短轴长,四舍五入到三位小数。
样例输入:
样例一:
2
1 0
-1 0
0
2
样例二:
3
1 1
-1 -1
0 0
45
7
样例输出:
样例一:
0.500
样例二:
0.202
题解:
发现题目意思是最小椭圆覆盖,然而我只会做最小圆覆盖,然后就不会做了怎么办?那就把它当做最小圆覆盖来做吧!先把坐标轴按规定的椭圆的长轴旋转,然后再把横坐标缩小p倍后就可以用圆来覆盖了。
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #define setfile() #else #define debug(...) #define filename "" #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout); #endif #define R register #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) char B[1 << 15], *S = B, *T = B; inline int FastIn() { R char ch; R int cnt = 0; R bool minus = 0; while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; ch == '-' ? minus = 1 : cnt = ch - '0'; while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus ? -cnt : cnt; } #define maxn 50010 #define pi (acos(-1)) struct Point { double x, y; }p[maxn], o; inline Point cir(R Point A, R Point B, R Point C) { R Point res; R double a1 = B.x - A.x, b1 = B.y - A.y, c1 = a1 * a1 + b1 * b1; R double a2 = C.x - A.x, b2 = C.y - A.y, c2 = a2 * a2 + b2 * b2; R double d = (a2 * b1 - a1 * b2) * 2; res.x = A.x + (c2 * b1 - c1 * b2) / d; res.y = A.y + (c1 * a2 - c2 * a1) / d; return res; } #define dist(_i, _j) ((_i.x - _j.x) * (_i.x - _j.x) + (_i.y - _j.y) * (_i.y - _j.y) ) #define eps 1e-9 int main() { //setfile(); R int n = FastIn(); for (R int i = 1; i <= n; ++i) p[i] = (Point) {FastIn() * 1.0 , FastIn() * 1.0}; R double aph = FastIn(), a = FastIn(); aph = (aph / 180.0) * pi; R double sina = sin(aph), cosa = cos(aph); for (R int i = 1; i <= n; ++i) { R double x0 = p[i].x, y0 = p[i].y; p[i].x = (x0 * cosa + y0 * sina ) / (a * 1.0); p[i].y = (y0 * cosa - x0 * sina); } std::random_shuffle(p + 1, p + n + 1); R double r2 = 0; o = p[1]; for (R int i = 2; i <= n; ++i) if (dist(p[i], o) > r2 + eps) { o = p[i]; r2 = 0; for (R int j = 1; j < i; ++j) if (dist(p[j], o) > r2 + eps) { o.x = (p[i].x + p[j].x) / 2.0; o.y = (p[i].y + p[j].y) / 2.0; r2 = dist(p[i], o); for (R int k = 1; k < j; ++k) if (dist(p[k], o) > r2 + eps) { o = cir(p[i], p[j], p[k]); r2 = dist(p[i], o); } } } printf("%.3lf\n",sqrt(r2) ); return 0; } /* input: 3 1 1 -1 -1 0 0 90 7 output: 0.202 input: 2 1 0 -1 0 0 2 output: 0.500 */