zoukankan      html  css  js  c++  java
  • CodeForces 47E. Cannon(离线暴力+数学)

    E. Cannon
    time limit per test
    3 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Bertown is under siege! The attackers have blocked all the ways out and their cannon is bombarding the city. Fortunately, Berland intelligence managed to intercept the enemies' shooting plan. Let's introduce the Cartesian system of coordinates, the origin of which coincides with the cannon's position, the Ox axis is directed rightwards in the city's direction, the Oy axis is directed upwards (to the sky). The cannon will make n more shots. The cannon balls' initial speeds are the same in all the shots and are equal to V, so that every shot is characterized by only one number alphai which represents the angle at which the cannon fires. Due to the cannon's technical peculiarities this angle does not exceed 45 angles (π / 4). We disregard the cannon sizes and consider the firing made from the point (0, 0).

    The balls fly according to the known physical laws of a body thrown towards the horizon at an angle:

    vx(t) = V·cos(alpha)
    vy(t) = V·sin(alpha)  –  g·t
    x(t) = V·cos(alphat
    y(t) = V·sin(alphat  –  g·t2 / 2

    Think of the acceleration of gravity g as equal to 9.8.

    Bertown defends m walls. The i-th wall is represented as a vertical segment (xi, 0) - (xi, yi). When a ball hits a wall, it gets stuck in it and doesn't fly on. If a ball doesn't hit any wall it falls on the ground (y = 0) and stops. If the ball exactly hits the point (xi, yi), it is considered stuck.

    Your task is to find for each ball the coordinates of the point where it will be located in the end.

    Input

    The first line contains integers n and V (1 ≤ n ≤ 104, 1 ≤ V ≤ 1000) which represent the number of shots and the initial speed of every ball. The second line contains n space-separated real numbers alphai (0 < alphai < π / 4) which represent the angles in radians at which the cannon will fire. The third line contains integer m (1 ≤ m ≤ 105) which represents the number of walls. Then follow m lines, each containing two real numbers xi and yi (1 ≤ xi ≤ 1000, 0 ≤ yi ≤ 1000) which represent the wall’s coordinates. All the real numbers have no more than 4 decimal digits. The walls may partially overlap or even coincide.

    Output

    Print n lines containing two real numbers each — calculate for every ball the coordinates of its landing point. Your answer should have the relative or absolute error less than 10 - 4.

    Examples
    input
    Copy
    2 10
    0.7853
    0.3
    3
    5.0 5.0
    4.0 2.4
    6.0 1.9
    output
    Copy
    5.000000000 2.549499369
    4.000000000 0.378324889
    input
    Copy
    2 10
    0.7853
    0.3
    2
    4.0 2.4
    6.0 1.9
    output
    Copy
    10.204081436 0.000000000
    4.000000000 0.378324889

    题意:

       有一门大炮,坐标在(0,0)(0,0),和mm堵墙,现在大炮要射nn发炮弹,每发炮弹的初始速度v是一样的,射击角度为α(0<α<π/4),假设射击后经过时间t,重力加速度g=9.8,则有:

       x(t)=vcos(α)

       y(t)=vsin(α)gt

       x(t)=vx(t)t

       y(t)=vsin(α)tgt2/2

       给定m堵墙墙顶坐标(xi,yi),墙垂直于xx坐标轴,炮弹如果打到墙上,就会卡住;如果掉到地上,也不会再滚动。

       求这n发炮弹最终的位置

                                                          ----translate by 守望、copy from 洛谷

      题解:显然如果速度相同,角度在45度以内,那么角度越大的射的越高越远,所以如果矮的能越过的墙高的也能越过,把问题离线下来按照角度排序,模拟每个球会怎么走就可以了,显然每堵墙只会被访问一遍,均摊复杂度O(1),总复杂度O(n)

      代码如下:

      

    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    struct bomb
    {
        int id;
        double a,ansx,ansy;
    } b[10010];
    
    struct wall
    {
        double x,y;
    } w[100010];
    
    int n,m;
    double v;
    
    int cmp1(wall x,wall y)
    {
        if(x.x==y.x) return x.y<y.y;
        return x.x<y.x;
    }
    
    int cmp2(bomb x,bomb y)
    {
        return x.a<y.a;
    }
    
    int cmp3(bomb x,bomb y)
    {
        return x.id<y.id;
    }
    
    int main()
    {
        double g=9.8;
        scanf("%d %lf",&n,&v);
        for(int i=1; i<=n; i++)
        {
            scanf("%lf",&b[i].a);
            b[i].id=i;
        }
        scanf("%d",&m);
        for(int i=1; i<=m; i++)
        {
            scanf("%lf%lf",&w[i].x,&w[i].y);
        }
        sort(w+1,w+m+1,cmp1);
        sort(b+1,b+n+1,cmp2);
        int r=1;
        for(;; r++)
        {
            if(r>m)
            {
                r=m+1;
                break;
            }
            double t=w[r].x/(cos(b[1].a)*v);
            if(v*sin(b[1].a)*t-g*t*t/2<=w[r].y)
            {
                break;
            }
        }
        for(int i=1; i<=n; i++)
        {
            while(1)
            {
                if(r>m)
                {
                    r=m+1;
                    break;
                }
                double t=w[r].x/(cos(b[i].a)*v);
                if(v*sin(b[i].a)*t-g*t*t/2>=w[r].y) r++;
                else break;
            }
            double t=w[r].x/(cos(b[i].a)*v);
            if(r<=m)
            {
                b[i].ansy=(v*sin(b[i].a)*t)-(g*t*t/2);
                b[i].ansx=w[r].x;
            }
            else
            {
                b[i].ansy=0;
                b[i].ansx=(v*sin(b[i].a)/g)*v*cos(b[i].a)*2;
            }
        }
        sort(b+1,b+n+1,cmp3);
        for(int i=1; i<=n; i++)
        {
            if(b[i].ansy<0)
            {
                b[i].ansy=0;
                b[i].ansx=(v*sin(b[i].a)/g)*v*cos(b[i].a)*2;
            }
            printf("%.9lf %.9lf
    ",b[i].ansx,b[i].ansy);
        }
    }
  • 相关阅读:
    个人:我的2011生活看板
    个人管理:公司做的稻盛阿米巴培训笔记
    使用TOGAF来做业务架构 价值驱动产品开发
    30天敏捷结果(21)正面失败,吸取教训,改善结果
    2010年12月blog汇总:敏捷个人
    30天敏捷结果(25):固定时间,灵活范围
    101与金根回顾敏捷个人:(11)执行力
    团队管理:设计团队的一周
    云:构建云计算的核心技术与平台
    读书笔记:千万别学英语
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9559302.html
Copyright © 2011-2022 走看看