CF832C
题目链接: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的更多相关文章
随机推荐
- Linux 查看进程资源--ps、top命令
1,ps命令 ps能够给出当前系统中进程的快照.它能捕获系统在某一事件的进程状态 命令参数: a 显示所有进 ...
- Jmeter系列(8)- test plam测试计划参数详解
如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 前言 先了解下测试计划的作用:http ...
- 智能称体脂称实现(datasheet篇)
(本文均出于个人理解而写,仅用于学习和交流,某些过程可能不一定正确,希望各位提出意见进行交流,共同进步) TI的参考方案是采用AFE4300芯片 同时进行生物阻抗身体成分测量和体重测量,以MSP430 ...
- 题目分享Q
题意:给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大 分析:这可以说是换根法的裸题吧 首先考虑对一个给定的根如何计算,这应该是最简单的那种树形dp吧甚至可能都不算dp(好像 ...
- sequel pro无法连接mysql服务器
1. 添加用户 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_passwd' WITH GRANT OPTION; FLU ...
- E. XOR Guessing 交互题 Educational Codeforces Round 71 (Rated for Div. 2)
E. XOR Guessing 交互题. 因为这个数最多只有14位 0~13,所以我们可以先处理后面7位,然后再处理后面7位. 因为异或的性质,如果一个数和0异或,那么就等于本身. 所以我们第一次异或 ...
- P2766 最长不下降子序列问题 网络流重温
P2766 最长不下降子序列问题 这个题目还是比较简单的,第一问就是LIS 第二问和第三问都是网络流. 第二问要怎么用网络流写呢,首先,每一个只能用一次,所以要拆点. 其次,我们求的是长度为s的不下降 ...
- Spring官网阅读(十五)Spring中的格式化(Formatter)
文章目录 Formatter 接口定义 继承树 注解驱动的格式化 AnnotationFormatterFactory FormatterRegistry 接口定义 UML类图 FormattingC ...
- 深入理解CSS定位
CSS中有3种定位机制:普通流,浮动和绝对定位.除非专门指定,否则所有框都在普通流中定位.顾名思义,普通流中元素框的位置由HTML元素的位置决定.块级框一个接一个地垂直排列,框之间的垂直距离由框的垂直 ...
- Vue + Element-ui实现后台管理系统(2)---项目搭建 + ⾸⻚布局实现
项目搭建 + ⾸⻚布局实现 上篇对该项目做了个总述 :Vue + Element-ui实现后台管理系统(1) --- 总述 这篇主要讲解 项目搭建 + 后台⾸⻚布局实现 : 整体效果 后台首页按布局一 ...