标签:
题目链接http://acm.uestc.edu.cn/#/problem/show/27
这题是一道数学计算题,比较坑,花了我几天时间
公式推了挺久的,因为看起来麻烦所以放着几天都懒得做...毕竟暑假
题目给的变量名太蛋疼了,我这里作新的约定
防守员的坐标就是\((x_0, y_0)\),速度\(v_0\)
滚地球的速度是\(v\),沿x轴分速度为\(v_x\),y轴分速度为\(v_y\)
高飞球的落点是\((x,y)\),飞行时间\(t\)
难点在于滚地球,要求是只要某个内场的恰好碰到球或者提前到达轨迹才可以
不要求在内场碰到,我一开始以为是在内场碰到滚地球
这样的话题目就变成了求一个某个二次函数在\(\left[0, \frac{r}{\sqrt{x^2+y^2}}\right]\)有没有解的情况
如果不在内场就简单多了,只要求某个二次函数在\([0, +\infty)\)有没有解即可
先讲高飞球,很简单,计算一下\(\sqrt{(x-x_0)^2+(y-y_0)^2}\)和\(vt\)的关系即可
这个关系式简单吧,我觉得不需要解释
然后是滚地球,要使人球能接触,则要求内场防守员跑到球的时间\(t\)满足以下条件\[\sqrt{(v_xt-x_0)^2+(v_yt-y_0)^2}\le v_0t\]
这是个关于t的二次不等式,我们将两边平方并移项合并,且因为\(v_x^2+v_y^2=v^2\),得:\[(v^2-v_0^2)t^2-2(v_xx_0+v_yy_0)t+(x_0^2+y_0^2)\le0\]
很漂亮的不等式,只要这个不等式在\(t\in [0,\infty)\)有解即可
当\(v\ge v_0\)时,这是显然有解的
当\(v < v_0\)时,函数\(f(t)=(v^2-v_0^2)t^2-2(v_xx_0+v_yy_0)t+(x_0^2+y_0^2)\)的对称轴为\(t_0=\frac{v_xx_0+v_yy_0}{v^2-v_0^2} > 0\)
所以只需要
\[
\begin{align*}
\Delta&=4(v_xx_0+v_yy_0)^2-4(v^2-v_0^2)(x_0^2+y_0^2)\\
&=4(v_x^2x_0^2+v_y^2y_0^2+2v_xv_yx_0y_0-v^2x_0^2-v^2y_0^2+v_0^2x_0^2+v_0^2y_0^2)\\
&=4[v_0^2(x_0^2+y_0^2)-v_y^2x_0^2+2v_xv_yx_0y_0-v_x^2y_0^2]\\
&=4[v_0^2(x_0^2+y_0^2)-(v_yx_0-v_xy_0)^2]\geq0
\end{align*}
\]
亦即\(v_0^2(x_0^2+y_0^2)\geq(v_yx_0-v_xy_0)^2\)
所以综上所述,只要一个内场防守员满足\(v\ge v_0\)或\(v_0^2(x_0^2+y_0^2)\geq(v_yx_0-v_xy_0)^2\)打击者就out
所以打成代码如下
#include <cstdio> #include <cmath> using namespace std; #define EPS (1e-8) int N, M; int X[10], Y[10], V[10]; char ball; double XX, YY, T; int H, L, VV; double vx, vy; bool safe; inline double sqr(double x) { return x * x; } int main() { while (scanf("%d%d", &N, &M) && N && M) { for (int i = 0; i < N; ++i) scanf("%d%d%d", &X[i], &Y[i], &V[i]); while (M--) { safe = true; while ((ball = getchar()) != ‘F‘ && ball != ‘G‘); switch (ball) { case ‘G‘: scanf("%d/%d%d", &H, &L, &VV); vx = VV * L / sqrt(sqr(H) + sqr(L)); vy = VV * H / sqrt(sqr(H) + sqr(L)); for (int i = 0; i < N; ++i) if (sqr(X[i]) + sqr(Y[i]) < 400) safe &= VV > V[i] && (sqr(X[i]) + sqr(Y[i])) * sqr(V[i]) < sqr(X[i] * vy - Y[i] * vx); break; case ‘F‘: scanf("%lf%lf%lf", &XX, &YY, &T); for (int i = 0; i < N; ++i) safe &= sqr(XX - X[i]) + sqr(YY - Y[i]) > sqr(V[i] * T); break; } if (safe) puts("SAFE"); else puts("OUT"); } } return 0; }
标签:
原文地址:http://www.cnblogs.com/johnsonyip/p/5662156.html