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的更多相关文章
随机推荐
- spring boot 集成mybatis使用logback打印并保存日志信息
spring boot 打印执行的sql语句 最近在学习spring boot 整合了Mybatis和druid之后总感觉少点什么东西,看了下在别的项目上用的框架,发现自己整合的东西不打印sql语句, ...
- centos6.5宽带拨号上网
CentOS6以后要安装rp-pppoe这个软件,centos之前的版本是adsl-setup命令安装. (1)查看是否安装 #rpm -qa|grep rp-pppoe 没有内容输出则没安装,若可以 ...
- Norwegian Wood
0 前言 <挪威的森林>是村上春树很有名的一部小说,但我想大多数人阅读的时候都只是把书名当作一个符号,而不是作为故事去追究. 我国台湾知名文学评论家杨照先生说过:村上的书里有太多太多典故, ...
- 图论--2-SAT--HDU/HDOJ 4115 Eliminate the Conflict
Problem Description Conflicts are everywhere in the world, from the young to the elderly, from famil ...
- 题解 CF160B 【Unlucky Ticket】
本文为UserUnknown原创 思路 这道题应该怎么做? 可以把输入的数字逐位拆分后存入数组,就像这样存进去: int a[N],b[N] tmp=n; k=1; while(--tmp){ a[k ...
- MySQL 子查询——查询最大值
子查询指将一个查询语句嵌套在另一个查询语句中.子查询可以在 SELECT.UPDATE 和 DELETE 语句中使用,而且可以进行多层嵌套.在实际开发时,子查询经常出现在 WHERE 子句中.子查询在 ...
- Linux下使用Rsync进行文件同步
数据备份方案 1.需要备份的文件目录有(原则上,只要运维人员写入或更改的数据都需要备份)./data,/etc/rc.local,/var/spool/cron/root等,根据不同都服务器做不同的调 ...
- CGI (通用网关接口)
CGI cgi即 Common Gateway Interface 译作 通用网关接口 是应用程序与应用程序之间的输入输出协议.比如我们写信,规定了开头一句写称呼,中间写内容,最后署名和日期.看到这种 ...
- SpringBoot:扩展SpringMVC、定制首页、国际化
目录 扩展使用SpringMVC 如何扩展SpringMVC 为何这么做会生效(原理) 全面接管SpringMVC 首页实现 页面国际化 SpringBoot扩展使用SpringMVC.使用模板引擎定 ...
- [C#]基础——注意事项
1. 静态类必须直接继承Object 2. 静态类不能实现接口,不能继承其他类(除了Object) 3.静态类中不能有实体方法 4.实体类中可以有静态方法,使用同 静态类 5.readonly属性可以 ...