/*
translation:
可以从任意方向以速度v发射一只白鸟,可在任意时刻产下一枚卵。发射后鸟将以抛物线轨迹飞行。空中有若干障碍物,问鸟
产下的卵是否能击中目标(x,y)
solution:
极限情况的离散化
note:
* 考虑到鸟的飞行轨迹是无数种方案的,所以只需考虑其中的极限情况,即擦着障碍物的边飞过去。所以可以枚举飞行轨迹
经过的点,也就是每个障碍的左上和右上2个顶点,之后求出飞行轨迹。判断是否经过其它的障碍物。
# 思路简单,但是编码麻烦,考虑的各种情况比较繁多。
*/
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
const int maxn = 100;
const double g = 9.8;
const double EPS = 1e-10;
int n, v, X, Y;
int L[maxn], B[maxn], R[maxn], T[maxn];
void solve_equation(double x, double y, double& vx0, double& vy0, double& vx1, double& vy1)
{
double a = g * g / 4, b = g * y - v * v, c = x * x + y * y;
double D = b * b - 4 * a * c;
if(D < 0 && D > -EPS) D = 0;
if(D < 0) {
vx0 = vx1 = -1;
vy0 = vy1 = -1;
return;
}
double t20 = (-b + sqrt(D)) / (2 * a), t21 = (-b - sqrt(D)) / (2 * a);
if(t20 <= 0) {
vx0 = vy0 = -1;
return;
}
double t0 = sqrt(t20);
vx0 = x / t0;
vy0 = (y + g * t0 * t0 / 2) / t0;
if(t21 <= 0) {
vx1 = vy1 = -1;
return;
}
double t1 = sqrt(t21);
vx1 = x / t1;
vy1 = (y + g * t1 * t1 / 2) / t1;
}
double calculate_y(double vy, double t)
{
return vy * t - g * t * t / 2;
}
int cmp(double lb, double ub, double a)
{
return a < lb + EPS ? -1 : a > ub - EPS ? 1 : 0;
}
bool check(double x, double y) //检查抛物线经过点x,y时是否能够满足要求
{
double vx[2], vy[2]; //根据抛物线求出水平方向和垂直方向的速度
solve_equation(x, y, vx[0], vy[0], vx[1], vy[1]);
for(int i = 0; i < 2; i++) {
if(vx[i] < 0 || vy[i] < 0) continue; //解是否有意义
if(calculate_y(vy[i], X / vx[i]) < Y - EPS) continue; //抛物线是否可行
//检测抛物线途中是否有障碍物
bool has_obstacle = false;
for(int j = 0; j < n; j++) {
if(L[j] >= X) continue;
if(R[j] == X && Y <= T[j] && calculate_y(vy[i], X / vx[i]) >= B[j]) has_obstacle = true;
int yl = cmp(B[j], T[j], calculate_y(vy[i], (double)L[j] / vx[i]));
int yr = cmp(B[j], T[j], calculate_y(vy[i], (double)R[j] / vx[i]));
int xh = cmp(L[j], R[j], vx[i] * (vy[i] / g));
int yh = cmp(B[j], T[j], calculate_y(vy[i], vy[i] / g));
if(yl * yr <= 0) has_obstacle = true;
if(xh == 0 && yh >= 0 && yl < 0) has_obstacle = true;
}
if(!has_obstacle) return true;
}
return false;
}
bool solve()
{
for(int i = 0; i < n; i++) R[i] = min(X, R[i]);
if(check(X, Y)) return true;
for(int i = 0; i < n; i++) {
if(check(L[i], T[i]) || check(R[i], T[i]))
return true;
}
return false;
}
int main()
{
//freopen("in.txt", "r", stdin);
while(cin >> n >> v >> X >> Y) {
for(int i = 0; i < n; i++) {
cin >> L[i] >> B[i] >> R[i] >> T[i];
}
if(solve()) printf("Yes\n");
else printf("No\n");
}
return 0;
}
aoj2308(#离散化,极限情况)
最新推荐文章于 2021-07-02 11:27:53 发布