zoj 1104 Leaps Tall Buildings(スーパーマンは飛ばない--.)

2868 ワード

この問題はちょうど幾何学を計算することを始める時やり遂げて、いかんせん少し軽視して分からないで、今日またこの問題を見て、決心してそれをAにしました==.
まず頂点をすべて求め,次に放物線のVと角度と放物線方程式(y=ax^2+bx+c)の関係である.
わかる
x = Vx * t;
y = Vy * t - 1/2*g*t*t;

両者を連立し,tを消去すると放物線方程式が得られた.
そして私のやり方は、二分放物線二次項係数aであり、始点と終点が知られているため、bとaの関係は自然に−b/(2 a)が極値点x座標であり、このxは最初の点と最後の点の中点x座標に違いない.
そしてa,bを求め,さらに導出した関係からVと角度を求めればよい.
私は高校の数学+物理の混合問題をしているような気がします..T T..
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")
#define STOP system("pause")

using namespace std;

const int MAX = 110;
const double g = 9.8;
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
bool dy(double x,double y)	{	return x > y + eps;}	// x > y 
bool xy(double x,double y)	{	return x < y - eps;}	// x < y 
bool dyd(double x,double y)	{ 	return x > y - eps;}	// x >= y 
bool xyd(double x,double y)	{	return x < y + eps;} 	// x <= y 
bool dd(double x,double y) 	{	return fabs( x - y ) < eps;}  // x == y
struct point {
    double x,y;
    void p(double xx, double yy)
    {
        x = xx; y = yy;
    }
};
point p[MAX];

double B(double a,double s)
{
    return -2*a*s;
}

int solve(double a, double b, int cnt)
{
    bool flag = false;
    for(int i=1; i<cnt-1; i++)
    {
        double x = p[i].x; 
        double y = p[i].y;
        if( xy(a*x*x + b*x, y) ) return 1;
        if( dd(a*x*x + b*x, y) ) flag = true;
    }
    if( flag ) return 0;
    return -1;
}

int main()
{
    int n;
    double sy, sx;
    while( ~scanf("%d", &n) )
    {
        double ss = 0;
        int cnt = 0;
        for(int i=0; i<n; i++)
        {
            scanf("%lf%lf", &sy, &sx);
            p[cnt].x = ss;
            p[cnt++].y = sy;
            p[cnt].x = ss + sx;
            p[cnt++].y = sy;
            ss += sx;
        }
        
        double begin = eps, end = inf;
        
        double s = p[cnt-1].x / 2, b, mid;
        while( begin <= end )
        {
            mid = (begin + end)/2;
            b = B(-mid, s);
            int ans = solve(-mid, b, cnt);
            if( ans == 0 ) break;
            if( ans == 1 )  //       
                begin = mid;
            else
                end = mid;
        }
        
        double ang = atan(b);
        double v = sqrt(g/(2*mid))/cos(ang);
        
        printf("%.2lf %.2lf
", ang/pi*180, v); } return 0; }