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的更多相关文章
随机推荐
- VulnHub靶场学习_HA: Chanakya
HA-Chanakya Vulnhub靶场 下载地址:https://www.vulnhub.com/entry/ha-chanakya,395/ 背景: 摧毁王国的策划者又回来了,这次他创造了一个难 ...
- 网络传输 socket
一.Socket语法及相关 前言:osi七层模型: 第七层:应用层. 各种应用程序协议,如HTTP,FTP,SMTP,POP3. 第六层:表示层. 信息的语法语义以及它们的关联,如加密 ...
- python 列表加法"+"和"extend"的区别
相同点 : "+"和"extend"都能将两个列表成员拼接到到一起 不同点 : + : 生成的是一个新列表(id改变) extend : 是将一个列表的成员 ...
- 在服务器本地监控服务端口命令之ss
在服务器本地监控服务端口命令之ss 当服务器的socket连接数量变得非常大时,无论是使用netstat命令还是直接cat /proc/net/tcp,执行速度都会很慢.可能你不会有 切身的感受,但当 ...
- sphinx的使用
1.下载地址 http://sphinxsearch.com/downloads/release/ 2.将其解压到D:\sphinx,并在D:\sphinx下新建目录data(用来存放索引文件)与lo ...
- CF--思维练习--CodeForces - 221C-H - Little Elephant and Problem (思维)
ACM思维题训练集合 The Little Elephant has got a problem - somebody has been touching his sorted by non-decr ...
- ACM--[kuangbin带你飞]--专题1-23
专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 FliptilePOJ 1426 Find T ...
- P1460 健康的荷斯坦奶牛 Healthy Holsteins (简单的dfs)
题目描述 农民JOHN以拥有世界上最健康的奶牛为傲.他知道每种饲料中所包含的牛所需的最低的维他命量是多少.请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少. 给出牛所需的最低的维他命 ...
- Linux之进程管理工具supervisor
环境:CentOS 7官方文档:http://supervisord.org/ 安装 # yum install -y epel-release # yum install -y supervisor ...
- 【Java8新特性】Lambda表达式基础语法,都在这儿了!!
写在前面 前面积极响应读者的需求,写了两篇Java新特性的文章.有小伙伴留言说:感觉Lambda表达式很强大啊!一行代码就能够搞定那么多功能!我想学习下Lambda表达式的语法,可以吗?我的回答是:没 ...