「Aizu2308」White Bird【计算几何】

本文探讨了在无障碍物的环境下,通过调整发射角度和速度,使愤怒小鸟中的白色小鸟能够准确击中目标猪的算法。分析了小鸟飞行轨迹、碰撞判断及优化策略。

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 ) (X, Y) (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.8 m / s 2 . 9.8 {\rm m/s^2}. 9.8m/s2. Gravity exerts a force on the objects in the decreasing direction of y y y-coordinate.

Input

A dataset follows the format shown below:

N   V   X   Y N\ V\ X\ Y N V X Y
L 1 B 1 R 1 T 1 L_1 B_1 R_1 T_1 L1B1R1T1
. . . ... ...
L N B N R N T N L_N B_N R_N T_N LNBNRNTN

All inputs are integer.

N N N: the number of obstacles
V V V: the initial speed of the white bird
X , Y X, Y X,Y: the position of the pig
( 0 ≤ N ≤ 50 , 0 ≤ V ≤ 50 , 0 ≤ X , Y ≤ 300 , X ≤ 0 ) (0 \leq N \leq 50, 0 \leq V \leq 50, 0 \leq X, Y \leq 300, X \leq 0) (0N50,0V50,0X,Y300,X0)

for 1 ≤ i ≤ N 1 \leq i \leq N 1iN,

L i L_i Li: the x x x-coordinate of the left side of the i i i-th obstacle
B i B_i Bi: the y y y-coordinate of the bottom side of the i i i-th obstacle
R i R_i Ri: the x x x-coordinate of the right side of the $i4-th obstacle
T i T_i Ti: the $y4-coordinate of the top side of the i i i-th obstacle
( 0 ≤ L i , B i , R i , T i ≤ 300 ) (0 \leq L_i, B_i, R_i, T_i \leq 300) (0Li,Bi,Ri,Ti300)

It is guaranteed that the answer remains unaffected by a change of L i , B i , R i L_i, B_i, R_i Li,Bi,Ri and T i T_i Ti in 1 0 − 6 . 10^{-6}. 106.

Output

Y e s / N o Yes/No 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 1
1 1 2 2

Output for the Sample Input 2

No

Sample Input 3

1 7 2 2
0 1 1 2

Output for the Sample Input 3

No

题意

  • 就是在愤怒的小鸟的游戏中,给你 N N N个长方形的障碍物,小鸟从 ( 0 , 0 ) (0,0) (0,0)处以大小为 V V V的速度射出,问能否下蛋砸中位于 ( X , Y ) (X,Y) (X,Y)处的猪

题解

  • 可以枚举小鸟经过每一个长方形的四个顶点,如果这时能砸中,则答案为 Y e s Yes Yes
  • 原因是假设不经过任何长方形的任何顶点,总可以通过调整使得经过某个长方形的顶点使得轨迹经过某个顶点
  • 简单说一下小鸟会不会撞上某个长方形的方法:可以算出经过长方形左边界时的位置与长方形上下边界的关系,然后算出从右边界射出的位置来判定会不会撞上
  • 当然需要注意 / 0 /0 /0的情况,好像这题不需要太注意精度

代码

#include<bits/stdc++.h>

using namespace std;
const int maxn=55;
const double g=9.8;
const double eps=1e-8;

double lx[maxn],ly[maxn],rx[maxn],ry[maxn],x,y,v;
int n;

int sgn(double k)
{
    return k<-eps?-1:(k<eps?0:1);
}

double calc(double vv,double t)
{
    return vv*t-g*t*t/2;
}

bool check(double ex,double ey)
{
    double a=4*ex*ex+4*ey*ey,b=4*ey*ex*ex*g-4*ex*ex*v*v,c=g*g*ex*ex*ex*ex;
    double vx,vy,vx2;
    double k=b*b-4*a*c;
    k+=eps;
    if(k<0) return false;

    for(int d=-1;d<=1;d+=2) {
        vx2=(-b+d*sqrt(k))/(2*a);
        vx2+=eps;
        if(vx2<=0) continue;

        vx=sqrt(vx2);vy=sqrt(v*v-vx*vx);

        bool ok=true;
        double ty=calc(vy,x/vx);
        if(sgn(ty-y)<0) continue;
        for(int i=1;i<=n;i++) {
            if(sgn(lx[i]-x)>=0) continue;
            if(sgn(rx[i]-x)>=0&&sgn(lx[i]-x)<=0&&sgn(ly[i]-ty)<0&&sgn(ry[i]-y)>0) ok=false;
            double zuoy=calc(vy,lx[i]/vx),youy=calc(vy,min(rx[i],x)/vx),topy=vy*vy/(2*g);
            if(sgn(zuoy-ly[i])<=0) {
                if(sgn(ly[i]-youy)<0) ok=false;
                else if(sgn(topy-ly[i])>0&&sgn(vx*(vy/g)-min(rx[i],x))<0&&sgn(vx*(vy/g)-lx[i])>0) ok=false;
            }
            else if(sgn(zuoy-ly[i])>0&&sgn(zuoy-ry[i])<0) ok=false;
            else{
                if(sgn(youy-ry[i])<0) ok=false;
            }
        }
        if(ok) return true;
    }
    return false;
}

int main()
{
    scanf("%d %lf %lf %lf",&n,&v,&x,&y);
    for(int i=1;i<=n;i++) scanf("%lf %lf %lf %lf",&lx[i],&ly[i],&rx[i],&ry[i]);
    if(check(x,y)) return printf("Yes\n"),0;
    for(int i=1;i<=n;i++) {
        if(check(lx[i],ly[i])) return printf("Yes\n"),0;
        if(check(lx[i],ry[i])) return printf("Yes\n"),0;
        if(check(rx[i],ly[i])) return printf("Yes\n"),0;
        if(check(rx[i],ry[i])) return printf("Yes\n"),0;
    }
    printf("No\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值