📜  门| GATE CS 2018 |第 41 题(1)

📅  最后修改于: 2023-12-03 14:58:19.966000             🧑  作者: Mango

门 | GATE CS 2018 | 第 41 题

题目描述:

有一扇门,有一个小孔。这个孔有一个随机的位置,并且可以在门中沿着水平方向移动。 一只手套放置在门的一侧,你必须使用给定的神奇子弹打中孔。 每颗子弹在打中门时从起始点弹开,偏移一定角度后沿直线飞行。 子弹击中门时,它会反弹,与门的其他一侧相交,然后弹回,并继续以相同的角度原路返回到初始点。 显然,在门的秉持下,子弹可以穿过孔吗?

输入:

第一行包含一个整数 $T$,表示测试用例的数量。对于每个测试用例,第一行包含一个代表米的整数 $h$,第二行包含三个代表初始弹球速度 $v$(以米/秒为单位),弹球发射角度 $\theta$(以度为单位)和门与水平轴的初始位置 $x$(以米为单位)。

输出:

对于每个测试用例,如果弹球可以穿过门,则输出“ YES”(不带引号)。否则,输出 “NO”(不带引号)。

样例输入:

2 3 3 45 1 1 1 1 1

样例输出:

YES NO

解释:

在第一个测试用例中,弹球在初始点以 $45^{\circ}$ 发射,从门的右侧进入,打在门的左侧,反弹到右侧,再次击中的孔。

在第二个测试用例中,弹球以 $45^{\circ}$ 发射,从门的右侧进入,但沿着对角线移动,永远无法击中孔。

解题思路

本题可以利用物理知识和程序设计相结合,具体思路如下:

  • 根据开口位置、弹球速度(v)、发射角度($\theta$)以及门与水平轴的初始位置(x)求出初始撞击位置(y)
  • 利用物理反弹的规律,求出弹球与门的第二次撞击位置
  • 判断弹球是否撞击到小孔,如果是则为YES,否则为NO
程序实现

代码如下:

import math

def can_pass(h: int, v: int, angle: int, x: int) -> str:
	#将角度转化为弧度
	theta = math.radians(angle)
	
	#计算初始撞击位置
	y = x * math.tan(theta) - (9.81 * x ** 2) / (2 * (v * math.cos(theta)) ** 2)

	#判断弹球是否能穿过门
	if h - y >= 1 and y >= 1:
		return "YES"
	else:
		return "NO"


if __name__ == "__main__":
    t = int(input())
    for _ in range(t):
        h = int(input())
        v, angle, x = map(int, input().split())
        print(can_pass(h, v, angle, x))

代码解释:

  • 处理每个测试用例时,先读取输入的门高度h和弹球的速度v、发射角度angle、门的初始位置x;
  • 然后,根据上述方法计算出弹球碰撞的位置y;
  • 接下来,判断弹球的下个碰撞是否落在门内部;
  • 如果是,返回“YES”,否则、返回 “NO”。