codeforce-24e 解题报告

Berland collider
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Recently the construction of Berland collider has been completed. Collider can be represented as a long narrow tunnel that contains nparticles. We associate with collider 1-dimensional coordinate system, going from left to right. For each particle we know its coordinate and velocity at the moment of start of the collider. The velocities of the particles don't change after the launch of the collider. Berland scientists think that the big bang will happen at the first collision of particles, whose velocities differs in directions. Help them to determine how much time elapses after the launch of the collider before the big bang happens.

Input

The first line contains single integer n (1 ≤ n ≤ 5· 105) — amount of particles in the collider. Next n lines contain description of particles. Each particle is described by two integers xivi ( - 109 ≤ xi, vi ≤ 109, vi ≠ 0) — coordinate and velocity respectively. All the coordinates are distinct.The particles are listed in order of increasing of coordinates. All the coordinates are in meters, and all the velocities — in meters per second. The negative velocity means that after the start of collider the particle will move to the left, and the positive — that the particle will move to the right.

Output

If there will be no big bang, output -1. Otherwise output one number — how much time in seconds elapses after the launch of the collider before the big bang happens. Your answer must have a relative or absolute error less than 10 - 9.

input
3
-5 9
0 1
5 -1
output
1.00000000000000000000
input
6
1 3
2 3
3 3
4 -3
5 -1
6 -100
output
0.02912621359223301065
  解题报告:

这道题考察的是二分法,二分法很简单,但关键是要知道二分的对象是什么,我刚开始只想到是对由速度和位置组成的点进行二分,求这些点组成的斜率的最大值,但是这种做法并不合适。其实真正二分的对象应该是 最终要求的对象--时间。

注意到对于这些点来说,他们相碰的最小时间是0(left),最大时间是1e9(right),因此我们由此可以进行二分。每次取其中点(mid),看在这个时间点有没有发生过碰撞,如果发生过碰撞,那么我们下一个搜索的时间段变为left-mid。如果没有发生过碰撞,那么下一个搜索的时间段变为mid-right。这样,最终挤出在精确度要求范围内的值。

在判断在某个时间点t是否发生碰撞时,也是由技巧的。我们从左到有遍历每个particle,如果他的速度为正,亦即其向右运动,那么我们就记录其在该时间点的位置(v*t + x),并且用max来几率位置这些向右运动的点达到的最大位置。如果速度相左,那么我们比较他在该时间点的位置与max的关系,如果大于,说明还没有碰撞,继续遍历。如过小于,证明已经发生过碰撞,返回true。

代码:

#include <iostream>
#include <stdio.h>
#include <iomanip>
using namespace std;
 int **a;
 int n;
bool check(double t);
int main()
{
  cin>>n;
  a = new int *[n];
  
  for(int i = 0;i < n;i++)
  a[i] = new int[2];
  
  for(int i = 0;i < n;i++)
  {
       scanf("%d %d",&a[i][0],&a[i][1]);
  }
  int total = 0;
  for(total = 0;total < n;total++)
  {
       if(a[total][1] > 0)
       {
          break;
       }
  }
  
  bool flag = true;
  for(int i = total;i < n;i++)   //判断是否会发生碰撞
  {
     if(a[i][1] < 0)
     { 
       flag = false;
       break;
     }
  }
  
  if(flag == true || total == n)
  {
     cout<<"-1"<<endl;
     return 0;
  }
 
 
  
  double left = 0;
  double right = 1e9;
 
  double mid;
  int i = 80;
  while(i > 0)  //这个地方没有用right-left小于1e-9作为判断条件,因为精度达不到。
  {
     i--;
     mid = (left + right)/2;
     
     if(check(mid) == true)   //二分法的应用
     { 
        right = mid;
     }
     
     else
     {
        left = mid;
     }     
  }
  
  cout<<fixed;
  cout<<setprecision(15)<<right<<endl;
 
}


bool check(double t)  //判断某个时间点是否会发生碰撞
{
   double max = -1e10;
   double temp;
   for(int i = 0;i < n;i++)
   {
      if(a[i][1] > 0)
      {
        temp = a[i][0] + a[i][1]*t;
        if(temp > max)
        max = temp;
      }
      else
      {
        if(a[i][0] + a[i][1]*t <= max)
        
        return true;
      }  
   }


   return false;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值