ZOJ 1104 Leaps Tall Buildings

题目大意:给出一些建筑物的高度与宽度,求出一条最矮的抛物线运动轨迹,能够跨过所有的建筑物。

输出初速度与水平方向的夹角,以及初速度的大小。

重力加速度取9.8m/(s^2)

思路:

因为该抛物线过固定点(0,0)和(D,0)(D为所有建筑物宽度之和),故设抛物线方程为:

y = A * x * ( x - D )

建立直角坐标系,得到最高的那一圈点的坐标。

例如第二组样例:

0 10.5

20 11.5

25 10

10 15

0 7

其对应坐标为:

(10.500000, 20.000000)

(22.000000, 25.000000)

(32.000000, 25.000000)

(47.000000, 10.000000)

(54.000000,  0.000000)

从第一个点枚举到第 n-1 个点求得不同的A,分别验证是否满足条件,在满足条件的抛物线中选择顶点最小的那一条。

角度angle = arctan(抛物线在(0,0)点的导数);

运用高中物理知识……

(g*t*t) / 2 = 抛物线顶点高度  =>   求出 t

速度= g * t / sin(angle)

 1 #include <cstdio>
 2 #include <cmath>
 3 
 4 const int MAXN = 100 + 10;
 5 const double INF = 1 << 30;
 6 const double PI = acos(-1);
 7 
 8 struct point
 9 {
10     double x, y;
11 };
12 
13 int n;
14 double A, D;
15 double maxHeight;
16 point P[MAXN];
17 double h[MAXN], d[MAXN];    //开始的时候一定要分开保存,我一开始直接读的点的坐标,结果WA了好几次
18 
19 double getA( double x, double y )   //根据第三个坐标点得到A的值
20 {
21     return y / ( x * ( x - D ) );
22 }
23 
24 double getY( double x, double tpA )  //根据当前的抛物线方程,给出横坐标x,返回纵坐标y
25 {
26     return tpA * x * ( x - D );
27 }
28 
29 double Judge( double tpA )          //判断该抛物线是否满足条件
30 {
31     for ( int i = 1; i < n; i++ )
32     {
33         double tt = getY( P[i].x, tpA );
34         if ( tt < P[i].y ) return -1;   //如果该x对应抛物线上的y值 小于该点坐标的y值,则不符合条件
35     }
36 
37     double pp = getY( D/2.0, tpA );
38     return pp;                     //若满足,返回最高点高度
39 }
40 
41 void FindMin()
42 {
43     D = d[n];
44     maxHeight = INF;
45     for ( int i = 1; i < n; i++ )
46     {
47         double H;
48         double tpA = getA( P[i].x, P[i].y );
49 
50         H = Judge( tpA );
51 
52         if ( H > 0 && H < maxHeight )       //如果该抛物线符合条件,并且小于当前的最大值,则更新
53         {
54             maxHeight = H;
55             A = tpA;
56         }
57     }
58     return;
59 }
60 
61 int main()
62 {
63     d[0] = h[0] = 0;
64 
65     while ( scanf("%d", &n) != EOF )
66     {
67         double a;
68         for ( int i = 1; i <= n; i++ )
69         {
70             scanf("%lf%lf", &h[i], &a);
71             d[i] = d[i - 1] + a;
72         }
73 
74         for ( int i = 1; i < n; i++ )         //得到最外面那一圈点的坐标
75         {
76             P[i].x = d[i];
77             P[i].y = h[i] > h[i + 1] ? h[i] : h[i + 1];   
78         }
79 
80         FindMin();
81 
82         double angle = atan( - A * D );       //这里得到的角度是弧度,还应当转化一下
83 
84         double temp = A * ( D/2.0 ) * ( D/2.0 - D );
85         double t = sqrt( temp / 4.9 );
86         double v = 9.8 * t / sin(angle) ;
87 
88         printf("%.2f %.2f\n", angle * 180 / PI,  v);
89 
90     }
91 
92     return 0;
93 }
原文地址:https://www.cnblogs.com/GBRgbr/p/2610660.html