UVA - 1520 Flights (简单数学题)

题意:

有一个二维坐标平面,有n(n<=50000)个导弹会从x轴上某一点p[i]发射,轨迹为抛物线,最高点坐标为(x[i],y[i])。(i表示第i个导弹)(p,x,y<=50000)

现在有m(m<=20000)架飞机要在这个二维平面上平行x轴飞行。每架飞机给两个数l,r(l,r<=n)表示这架飞机飞行的时候导弹l,l+1,...,r正在发射中。给定该飞机的飞行区间x0[j],x1[j](<=50000),求每架飞机从x0[j]飞到到x1[j]最小离地面多高才不会被导弹打中。(j表示第j架飞机)

思路:

其实就是一个简单的数学题。我们直接求出每个导弹的曲线方程a*x*x+b*x+c,然后根据飞机飞行的区间取最大值即可。

我们已知三个条件:

-b/(2*a)=x[i]

a*x[i]*x[i]+b*x[i]+c=y[i]

a*p[i]*p[i]+b*p[i]+c=0

三个方程解出三个未知数。

暴力的时间复杂度是n*m=1e9  给了10秒的时限  580ms就过了。。。数据比较水,放心暴力。

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int mx=500010;
int n,m,k;
double max(double x,double y){if(x>y)return x;return y;}
double min(double x,double y){if(x<y)return x;return y;}
struct node{
    double x,y;
    double p;
    double a,b,c;
}dd[mx];
double ans[mx],tmp,cnt;
int main()
{
    ios::sync_with_stdio(false);
    int flag;
    int T=0;
    while(cin>>n)
    {
     if(T) puts("");
     T=1;
     for(int i=1;i<=n;i++)
     {
     cin>>dd[i].p>>dd[i].x>>dd[i].y;
     tmp=dd[i].y/(dd[i].x*dd[i].x+dd[i].p*dd[i].p-2*dd[i].x*dd[i].p);
     dd[i].a=-tmp;
     dd[i].b=2*dd[i].x*tmp;
     dd[i].c=dd[i].y-dd[i].x*dd[i].x*tmp;
     }
     cin>>m;
     int mm=m;
     memset(ans,0,sizeof(ans));
     int ii,jj;
     double xx,yy;
     int t=0;
     while(mm--)
     {t++;
         cin>>ii>>jj>>xx>>yy;
        for(int i=ii;i<=jj;i++)
        {
            double l=dd[i].p,r=2*dd[i].x-dd[i].p;
            if(xx>r||yy<l) continue;
            if(dd[i].x>=xx&&dd[i].x<=yy)
            {
                ans[t]=max(ans[t],dd[i].y);
                continue;
            }
            if(dd[i].x>yy)
            {
                tmp=dd[i].a*yy*yy+dd[i].b*yy+dd[i].c;
                ans[t]=max(ans[t],tmp);
            }
            if(dd[i].x<xx)
            {
                tmp=dd[i].a*xx*xx+dd[i].b*xx+dd[i].c;
                ans[t]=max(ans[t],tmp);
            }
        }
     }
     for(int i=1;i<=m;i++)
     cout<<fixed<<setprecision(9)<<ans[i]<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值