AOJ 2308 —— 计算几何

来源:互联网 发布:大学生借款软件 编辑:程序博客网 时间:2024/05/22 08:40

White Bird

Time Limit : 5 sec, Memory Limit : 65536 KB

White Bird

Angry Birds is a mobile game of a big craze all over the world. You were convinced that it was a waste of time to play the game, so you decided to create an automatic solver.

You are describing a routine that optimizes the white bird's strategy to defeat a pig (enemy) by hitting an egg bomb. The white bird follows a parabolic trajectory from the initial position, and it can vertically drop egg bombs on the way.

In order to make it easy to solve, the following conditions hold for the stages.

  • N obstacles are put on the stage.
  • Each obstacle is a rectangle whose sides are parallel to the coordinate axes.
  • The pig is put on the point (X,Y).
  • You can launch the white bird in any direction at an initial velocity V from the origin.
  • If the white bird collides with an obstacle, it becomes unable to drop egg bombs.
  • If the egg bomb collides with an obstacle, the egg bomb is vanished.

The acceleration of gravity is 9.8ms2. Gravity exerts a force on the objects in the decreasing direction of y-coordinate.

Input

A dataset follows the format shown below:

N V X Y
L1 B1 R1 T1

LN BN RN TN

All inputs are integer.

  • N: the number of obstacles
  • V: the initial speed of the white bird
  • XY: the position of the pig

(0N500V500X,Y300X0)

for 1iN,

  • Li: the x-coordinate of the left side of the i-th obstacle
  • Bi: the y-coordinate of the bottom side of the i-th obstacle
  • Ri: the x-coordinate of the right side of the i-th obstacle
  • Ti: the y-coordinate of the top side of the i-th obstacle

(0Li,Bi,Ri,Ti300)

It is guaranteed that the answer remains unaffected by a change of LiBiRi and Ti in 10−6.

Output

Yes/No

You should answer whether the white bird can drop an egg bomb toward the pig.

Sample Input 1

0 7 3 1

Output for the Sample Input 1

Yes

Sample Input 2

1 7 3 11 1 2 2

Output for the Sample Input 2

No

Sample Input 3

1 7 2 20 1 1 2

Output for the Sample Input 3

No

Source: ACM-ICPC Japan Alumni Group Summer Camp 2011 , Day 3, Tokyo, Japan, 2011-09-19 
http://acm-icpc.aitea.net/
挺有意思的一道题,情景是愤怒的小鸟。。。题意是一只小鸟从原点开始抛物线飞行,途中会有一堆障碍和一只猪,问你能否在飞行途中下一个蛋,砸到猪。蛋是垂直下落的。
思路:我们只要去考虑鸟能否飞到猪的正上方即可。把障碍分成线段,判断抛物线与线段是否相交,联立解方程组即可。我们逐渐降低这个角度直到恰好经过(X , Y)或恰好经过某个障碍物的左上角或右下角。
#include <cstdio>#include <cmath>#include <algorithm>#include <iostream>#include <cstring>#include <map>#include <string>#include <stack>#include <cctype>#include <vector>#include <queue>#include <set>#include <utility>#include <cassert>using namespace std;///#define Online_Judge#define outstars cout << "***********************" << endl;#define clr(a,b) memset(a,b,sizeof(a))#define lson l , mid  , rt << 1#define rson mid + 1 , r , rt << 1 | 1#define mk make_pair#define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)const int MAXN = 50 + 10;const int MAXS = 10000 + 50;const int sigma_size = 26;const long long LLMAX = 0x7fffffffffffffffLL;const long long LLMIN = 0x8000000000000000LL;const int INF = 0x7fffffff;const int IMIN = 0x80000000;const int inf = 1 << 30;#define eps 1e-8const long long MOD = 1000000000 + 7;const int mod = 100000;typedef long long LL;const double PI = acos(-1.0);typedef double D;typedef pair<int , int> pii;#define Bug(s) cout << "s = " << s << endl;///#pragma comment(linker, "/STACK:102400000,102400000")const double g = 9.8;int N , V , X , Y;int L[MAXN] , B[MAXN] , R[MAXN] , T[MAXN];///计算以vy的速度竖直向上射出t秒后的位置double calc(double vy , double t){    return vy * t - g * t * t / 2;}///判断a相对lb和ub的位置int cmp(double lb , double ub , double a){    return a < lb + eps ? -1 : a > ub - eps ? 1 : 0;}///判断当路径通过(qx , qy)时,蛋能否砸到猪。bool check(double qx , double qy){    ///初速度在xy方向上的分速度分别为vx , vy , 通过(qx , qy)的时间为t    ///求解联立方程式 vx^2 + vy^2 = V ^ 2 , vx * t = qx , vy * t - 1/2 * g * t^ 2 = qy;    double a = g * g / 4 , b = g * qy - V *  V , c = qx * qx + qy * qy;    double D = b * b - 4 * a * c;    if(D < 0 && D > -eps)D = 0;    if(D < 0)return false;    for(int d = -1 ; d <= 1 ;d += 2)///联立方程组的两个解    {        double t2 = (- b + d * sqrt(D)) / (2 * a);        if(t2 <= 0)continue;        double t = sqrt(t2);        double vx = qx / t , vy = (qy + g * t * t / 2) / t;        ///判断是否通过猪的正上方        double yt = calc(vy , X / vx);        if(yt < Y - eps)continue;        bool ok = true;        for(int i = 0 ; i < N ; i++)        {            if(L[i] >= X)continue;            ///判断猪和正上方的鸟之间是否有障碍物            if(R[i] == X && Y <= T[i] && B[i] <= yt)ok = false;            ///判断飞到猪的正上方之前是否会碰到障碍物            int yL = cmp(B[i] , T[i] , calc(vy , L[i] / vx));///左侧相对位置            int yR = cmp(B[i] , T[i] , calc(vy , R[i] / vx));///右侧相对位置            int xH = cmp(L[i] , R[i] , vx * (vy / g));///顶点相对位置            int yH = cmp(B[i] , T[i] , calc(vy , vy / g));            if(xH == 0 && yH >= 0 && yL < 0)ok = false;            if(yL * yR <= 0)ok = false;        }        if(ok)return true;    }    return false;}void solve(){    ///干掉猪以后的障碍物    for(int i = 0 ; i < N ; i++)    {        R[i] = min(R[i] , X);    }    bool ok = check(X, Y);///直接撞猪上了    for(int i = 0 ; i < N ; i++)    {        ok |= check(L[i] , T[i]);///经过左上角        ok |= check(R[i] , T[i]);///经过右下角    }    puts(ok ? "Yes" : "No");}int main(){    while(~scanf("%d%d%d%d" , &N , &V , &X , &Y))    {        for(int i = 0 ;i < N ; i++)scanf("%d%d%d%d" , &L[i] , &B[i] , &R[i] , &T[i]);        solve();    }    return 0;}