题目链接:http://codeforces.com/contest/832/problem/C

题目大意:

  n个人,面向左或者右站在同一条轴上,每个人在轴上的坐标为x,速度为v。请你在某个位置放置一个炸弹,炸弹一炸,每个人都会立即朝前跑。炸弹会发出一道怪光,速度s,如果人被这道怪光从身后追上,那么这个人的速度就会 s+v 。请你合理放置炸弹,使得从炸弹爆炸到有人跑到0并且有人跑到1e6所需的时间最短。

解题思路:

  比赛时这道题想了一个多小时,完全没有思路,思路来源于Tutorial

  从0到1e6二分时间,判断在这个时间是否可以达成目标,具体细节请看代码和注释,因为这一题的细节有一点多。

AC代码:

 #include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn=1e5+;
double s;
int n;
struct p{
double x,v;
int t;//t,1左;2右.
}man[maxn];
bool jiao(pair<double,double>l,pair<double,double>r){
//这里是边界情况讨论,非常恶心,其实就是说:因为这里讨论的坐标点都是整数,所以对于一个区间的左端点,我们要向右取整,对于右端点则要向左取整,这样最稳妥。
double ls=floor(l.second);
double lf=ceil(l.first);
double rs=floor(r.second);
double rf=ceil(r.first);
if(ls>=rf&&lf<=rs) return true;
if(rs>=lf&&rf<=ls) return true;
return false;
}
bool can(double time){ //判断函数
//********************************************
//一开始先假设用这么多时间无法到达左右端点
bool left=false,right=false;
pair<double,double>l,r; //l和r记录如果要到达左右端,炸弹可以放置的区间
l=r=make_pair(1e6*1.0,0.0); //这个区间就代表无法到达左右端点
//*****************************************
for(int i=;i<n;i++){
double xx=man[i].x,vv=man[i].v;
//接下来这部分只分析到达左端点这一部分,到达右端点的同理
//事实上,我在打这一部分的时候是左右端判断镜像进行的,这样比较不会乱
if(man[i].t==){
if(vv*time>=xx){ //如果光靠这个人自己走就能在这个时间内到达左端点,那么炸弹放在哪里就无所谓了
left=true;
l=make_pair(0.0,1e6*1.0);
}
else if((vv+s)*time>=xx){ //这是最优的情况,炸弹直接放在这个人脚下,一炸他马上就被加速
left=true;
double t=(time*vv+time*s-xx)/s; //(1)
double maxr=xx-vv*t+s*t; //(2)
//式子(1)、(2)其实就是求炸弹最右能放到哪里,不难想到,当炸弹放在最右,这个人刚好能在规定的时间到达左端
l.first=min(l.first,xx);
l.second=max(l.second,maxr);//更新区间
}
}
else{
if(vv*time>=1e6*1.0-xx){
right=true;
r=make_pair(0.0,1e6*1.0);
}
else if((vv+s)*time>=1e6*1.0-xx){
right=true;
double t=(s*time+vv*time-1e6*1.0+xx)/s;
double maxl=xx+vv*t-s*t;
r.first=min(r.first,maxl);
r.second=max(r.second,xx);
}
}
if(left&&right&&jiao(l,r)){//能到达左右端并且l和r有交集,证明这个时间可以到达
return true;
}
}
return false;
}
int main(){
scanf("%d%lf",&n,&s);
for(int i=;i<n;i++)
scanf("%lf%lf%d",&man[i].x,&man[i].v,&man[i].t);
double l=0.0,r=1e6*1.0;
for(int i=;i<;i++){ //循环100次就足够精确了
double m=(l+r)/2.0;
if(can(m)) r=m;
else l=m;
}
printf("%.7lf\n",l);
return ;
}

  

CF832C的更多相关文章

随机推荐

  1. 【集群实战】NFS服务常见故障排查和解决方法

    NFS,全名叫Network File System,中文叫网络文件系统,是Linux.UNIX系统的分布式文件系统的一个组成部分,可实现在不同网络上共享远程文件系统. NFS由Sun公司开发,目前已 ...

  2. 【三剑客】awk运算符

    1. 算术运算符:+,-,*,/,% [root@oldboy test]# awk 'BEGIN{a=50;b=20;print "(a+b)=",(a+b)}' (a+b)= ...

  3. Shiro踩坑记(二):使用RequiresXXX的注解后,访问对应请求返回404

    问题描述: 我在项目中的某个Controller上添加了@RequirePermissions注解,希望在执行该请求前,可以先进行权限验证.但是当我请求该Controller时,返回的确是404错误. ...

  4. Hawkeye部署Github监控系统

    2019独角兽企业重金招聘Python工程师标准>>> step1:python环境安装 #pwd /usr/local/soft #wget https://www.python. ...

  5. C++11的mutex和lock_guard,muduo的MutexLock 与MutexLockGuard

    互斥锁是用来保护一段临界区的,它可以保证某段时间内只有一个线程在执行一段代码或者访问某个资源. C++11的mutex和lock_guard C++11新增了mutex,使用方法和linux底下的常用 ...

  6. python-os.rmdir与shutil.rmtree的区别和用法

    每次写脚本的时候,pycharm都会自动生成缓存文件__pycache__文件,在提交代码的时候还得挨个删除,于是自己写一小段代码自动循环删除此目录及下面的文件. 思路: 先将目录及其下的文件读取出来 ...

  7. Scrapy爬虫快速入门

    安装Scrapy Scrapy是一个高级的Python爬虫框架,它不仅包含了爬虫的特性,还可以方便的将爬虫数据保存到csv.json等文件中. 首先我们安装Scrapy. pip install sc ...

  8. Jenkins+Ansible+Gitlab自动发布/回滚Spring项目

    一.实现方法流程图 流程图如下:代码托管在本地GitLab上(为了复现整套流水线,我直接使用了GitHub,懒得再搭建GitLab),开发完成后提交代码到代码仓库,[自动]触发Jenkins进行持续集 ...

  9. JavaScript 浅析数组对象与类数组对象

    数组(Array对象) 数组的操作 创建数组方法 添加与修改数组元素 删除数组元素 使用数组元素 遍历数组元素 多维数组 数组相关的函数 concat() join() pop() push() sh ...

  10. 【Spark】这一篇或许能让你大概了解如何通过JavaAPI实现DataFrame的相关操作

    文章目录 需求概述 步骤 一.创建Maven工程并导包 二.选用第一种方法:利用反射机制配合样例类构建DataFrame 开发代码 选用第二种方法:通过StrucType配合Row构建DataFram ...