欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CSUOJ-2092 Space Golf (物理模拟题)

程序员文章站 2022-07-07 15:15:28
...

CSUOJ-2092 Space Golf (物理模拟题)

Time Limit: 1 Sec Memory Limit: 512 Mb Submitted: 79 Solved: 37 SpecialJudge


Description
You surely have never heard of this new planet surface exploration scheme, as it is being carried out in a project with utmost secrecy. The scheme is expected to cut costs of conventional rover-type mobile explorers considerably, using projected-type equipment nicknamed “observation bullets”.

Bullets do not have any active mobile abilities of their own, which is the main reason of their cost-efficiency. Each of the bullets, after being shot out on a launcher given its initial velocity, makes a parabolic trajectory until it touches down. It bounces on the surface and makes another parabolic trajectory. This will be repeated virtually infinitely.

We want each of the bullets to bounce precisely at the respective spot of interest on the planet surface, adjusting its initial velocity. A variety of sensors in the bullet can gather valuable data at this instant of bounce, and send them to the observation base. Although this may sound like a conventional target shooting practice, there are several issues that make the problem more difficult.

  • There may be some obstacles between the launcher and the target spot. The obstacles stand upright and are very thin that we can ignore their widths. Once the bullet touches any of the obstacles, we cannot be sure of its trajectory thereafter. So we have to plan launches to avoid these obstacles.
  • Launching the bullet almost vertically in a speed high enough, we can easily make it hit the target without touching any of the obstacles, but giving a high initial speed is energy-consuming. Energy is extremely precious in space exploration, and the initial speed of the bullet should be minimized. Making the bullet bounce a number of times may make the bullet reach the target with lower initial speed.
  • The bullet should bounce, however, no more than a given number of times. Although the body of the bullet is made strong enough, some of the sensors inside may not stand repetitive shocks. The allowed numbers of bounces vary on the type of the observation bullets.
    You are summoned engineering assistance to this project to author a smart program that tells the minimum required initial speed of the bullet to accomplish the mission.

Figure D.1 gives a sketch of a situation, roughly corresponding to the situation of the Sample Input 4 given below.

CSUOJ-2092 Space Golf (物理模拟题)
Figure D.1. A sample situation
You can assume the following.

  • The surface of the planet and the bullets are made so hard that bounces can be approximated as elastic collisions. In other words, loss of kinetic energy on bounces can be ignored. As we can also ignore the atmospheric resistance, the velocity of a bullet immediately after a bounce is equal to the velocity immediately after its launch.
  • The bullets are made compact enough to ignore their sizes.
  • The launcher is also built compact enough to ignore its height.

You, a programming genius, may not be an expert in physics. Let us review basics of rigid-body dynamics.

We will describe here the velocity of the bullet v with its horizontal and vertical components vx and vy (positive meaning upward). The initial velocity has the components vix and viy, that is, immediately after the launch of the bullet, vx = vix and vy = viy hold. We denote the horizontal distance of the bullet from the launcher as x and its altitude as y at time t.

  • The horizontal velocity component of the bullet is kept constant during its flight when atmospheric resistance is ignored. Thus the horizontal distance from the launcher is proportional to the time elapsed.
    CSUOJ-2092 Space Golf (物理模拟题)

  • The vertical velocity component vy is gradually decelerated by the gravity. With the gravity acceleration of g, the following differential equation holds during the flight.
    CSUOJ-2092 Space Golf (物理模拟题)
    Solving this with the initial conditions of vy = viy and y = 0 when t = 0, we obtain the following.
    CSUOJ-2092 Space Golf (物理模拟题)
    The equation (4) tells that the bullet reaches the ground again when t = 2viy/g. Thus, the distance of the point of the bounce from the launcher is 2vixviy/g. In other words, to make the bullet fly the distance of l, the two components of the initial velocity should satisfy 2vixviy = lg.

  • Eliminating the parameter t from the simultaneous equations above, we obtain the following equation that escribes the parabolic trajectory of the bullet.
    CSUOJ-2092 Space Golf (物理模拟题)
    For ease of computation, a special unit system is used in this project, according to which the gravity acceleration g of the planet is exactly 1.0.

Input
The input consists of several tests case with the following format.
CSUOJ-2092 Space Golf (物理模拟题)

For each test, the first line contains three integers, d, n, and b. Here, d is the distance from the launcher to the target spot (1 ≤ d ≤ 10000), n is the number of obstacles (1 ≤ n ≤ 10), and b is the maximum number of bounces allowed, not including the bounce at the target spot (0 ≤ b ≤ 15).

Each of the following n lines has two integers. In the k-th line, pk is the position of the k-th obstacle, its distance from the launcher, and hk is its height from the ground level. You can assume that 0 < p1, pk < pk + 1 for k = 1, …, n − 1, and pn < d. You can also assume that 1 ≤ hk ≤ 10000 for k = 1, …, n.

Output
Output the smallest possible initial speed vi that makes the bullet reach the target. The initial speed vi of the bullet is defined as follows.
CSUOJ-2092 Space Golf (物理模拟题)
The output should not contain an error greater than 0.0001.

Sample Input
100 1 0
50 100

10 1 0
4 2

100 4 3
20 10
30 10
40 10
50 10

343 3 2
56 42
190 27
286 34

Sample Output
14.57738
3.16228
7.78175
11.08710


题意:

一颗子弹在水平面上跳跃,跳跃过程中忽略空气阻力,速度无损失,落地反弹也无速度损失,最多可以反弹跳跃b次击中终点(和起点的距离为d),路途中有n个木板障碍物(忽略厚度,距离起点x,高度为y),在跳跃过程中如果有木板挡住了,就不能往后跳跃了。 求能够到达终点的最小初速度(vx vy组合后输出)。
重力加速度为1

TIPS:

该题目主要是对题目的理解,然后进行物理公式推导,难度不大,但是要注意浮点数比较的精度问题,浮点数的比较需要使用EPS避免精度误差!


方法一:

思路:
总长度d已知,因此可以枚举反弹跳跃次数,那么可以计算出跳跃区间的长度,也就是抛物线的开口长度。然后枚举每个障碍物,计算要跳过这个木板的最小的抛物线中间高度h,然后就记录需要跳过所有木板的最小抛物线中间高度maxh【即最大的中间高度】。 那么只要速度能够跳过这个最高高度maxh,就一定可以跳过所有得障碍物。【下图部分1】
CSUOJ-2092 Space Golf (物理模拟题)
接着可以推出抛物线的中间高度H和初速度Vx和Vy的关系,并得到V^2和H的关系式,而H的取值一定要大于maxh,这样才能保证跳过所以障碍物。【上图部分2】
AC代码如下:

#include <iostream>
#include <stdio.h>
#include <math.h>
#define INF 0x3f3f3f3f

using namespace std;

const int maxn = 20;
const double EPS = 1e-6;
double d;//出发点到终点的距离
int n, b;//障碍物的个数,最大弹跳次数
int x[maxn], y[maxn];//障碍物坐标

int main()
{
    while(~scanf("%lf%d%d", &d, &n, &b))
    {
        for(int i = 0; i < n; i++)
            scanf("%d%d", &x[i], &y[i]);
        double ans = INF;//ans保持速度v的平方
        for(int i = 1; i <= b + 1; i++)//枚举弹跳间隔数
        {
            double m = d / i;//每一小个跳跃区间的长度
            int flag = 1;//标记是否能跳过所有障碍物
            double maxh = -1;//在弹跳次数为i时,要跳过每一个障碍物需要的最高抛物线中间高度
            for(int j = 0; j < n; j++)//枚举每一个障碍物
            {
                double dx = fmod(x[j], m), dy = y[j];//fmod浮点数求余数,dx为障碍物距离其所在跳跃区间起点的距离
                if(fabs(dx) <= EPS)//障碍物恰好在跳跃区间的起始点或落地点,这样一定会撞到
                {
                    flag = 0;
                    break;
                }
                double h = (m * m * dy) / (m - dx) / dx / 4.0;//跳过障碍物需要的抛物线中间高度
                maxh = max(maxh, h);//记录最大高度
            }
            if(!flag)
                continue;
            if(maxh < m / 4 + EPS)//双勾函数的极值点为m/4,此时函数取值为m
            ans = min(ans, m);
            else
                ans = min(ans, m * m / (8 * maxh) + 2 * maxh);
        }
        printf("%.6f\n", sqrt(ans));
    }
    return 0;
}

方法二:

思路:
对于起点终点固定的抛物线运动,可以证明当速度为45度时会达到最小,如果这个最小速度不足以通过所有的障碍物,那么也可以证明当该运动曲线刚好经过障碍物最高点时速度可以达到最小

由于反弹次数不超过15次,可以暴力枚举每一个反弹落地次数,这样就可以得到每一个跳跃区间的长度。首先判断45度时的速度能不能通过所有的障碍物;不能的话,对于每一个障碍物,都可以求得一个刚好经过该障碍物时的速度【共n种】,再判断该速度是不是能够通过所有的障碍物,最后取所以可行速度的最小值即可。

CSUOJ-2092 Space Golf (物理模拟题)

AC代码如下:

#include <iostream>
#include <stdio.h>
#include <math.h>
#define INF 0x3f3f3f3f

using namespace std;

const int maxn = 20;
const double EPS = 1e-7;
double d, m, vx, vy;//出发点到终点的距离, 跳跃区间的长度,初速度的xy分量
int n, b;//障碍物的个数,最大弹跳次数
double xx[maxn], y[maxn];//障碍物坐标
double x[maxn];//经过处理后,每个障碍物距离弹跳区间起始点的距离

void per(double dx, double dy)//要恰好通过某一障碍物,需要的vx, vy
{
    vy = sqrt((dy * m * m) / (2 * dx * (m - dx)));
    vx = m / 2 / vy;
}

bool jud()//判断以vx,vy是否能够通过所有障碍物
{
    for(int i = 0; i < n; i++)
    {
        double t = x[i] / vx;
        double h = vy * t - 0.5 * t * t;//能够跳的高度
        if(y[i] >= h + EPS)//障碍物比能跳高度高
            return false;
    }
    return true;
}

double sol(int cc)
{
    m = d / cc;
    for(int i = 0; i < n; i++)
        x[i] = fmod(xx[i], m);//fmod浮点数取余数,经过处理后,每个障碍物距离弹跳区间起始点的距离
    vx = vy = sqrt(m / 2);//45度时的速度
    if(jud())
        return vx * sqrt(2.0);
    double mi = INF;
    for(int i = 0; i < n; i++)//枚举每一个障碍物
    {
        per(x[i], y[i]);//要恰好通过某一障碍物,需要的vx, vy
        if(jud())
            mi = min(mi, sqrt(vx * vx + vy * vy));
    }
    return mi;
}

int main()
{
    while(~scanf("%lf%d%d", &d, &n, &b))
    {
        for(int i = 0; i < n; i++)
            scanf("%lf%lf", &xx[i], &y[i]);
        double ans = INF;
        for(int i = 1; i <= b + 1; i++)//枚举弹跳次数
            ans = min(ans, sol(i));
        printf("%.6f\n", ans);
    }
    return 0;
}
相关标签: 模拟