CodeForces 832 C. Strange Radiation

来源:互联网 发布:网络黑客高手微信群 编辑:程序博客网 时间:2024/05/10 20:33

原题链接: http://codeforces.com/problemset/problem/832/C


题意:

在一条x轴上,范围(0 ~ 10^6),有n个人在轴上奔跑,然后在某点放下一个炸弹。

炸弹爆炸后放出射线,如果当某一时刻,射线和某个人重合在同一点,那么这个人就会得到S的加速。

需要求的是,在最短时间内0点和10^6点都有人到达。

接下来我们知道n个人和射线的速度S。

分别给出每个人的初始位置,速度,和方向(1为左,2为右)。


题解:

首先确定最短时间t的查询用二分来查找。

对于每个人,如果往左跑,我们得找到一个合适的放炸弹的位置,使得这个人在t时间内能跑到0位置。

记d为人与0位置的距离,d1为人被炸弹追上时已经跑了多远

如果(d/vi)≤t,我们就可以将炸弹放在任何位置(就算没有炸弹加速也能按时到达)。   

否则,假设炸弹放在X,X满足以下:

1)在被射线追上前,人已经以vi奔跑距离为d1,被追上后再以vi+s的速度奔跑xi-d1的距离。

两段时间之和小于t。(x / vi) + ( vi + s ) <= t。

2)人向左跑,射线可以追上,那么炸弹一开始一定在人的右侧。xi  > d;

3)炸弹与人在d1/vi时相遇于d-d1处。这说明炸弹一开始位置x满足x=(d-d1)+(d1/vi)*s;

向右同理。


#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#include<math.h>#define ll long longusing namespace std;const int MAX = 1e6 + 5;const ll INF = 1e10;struct node {int x,v,dir;} per[MAX];int n,s;bool solve(double val) {ll l1 = 1e6,l2 = 0,r1 = 1e6,r2 = 0;ll f1 = 0,f2 = 0;for(int i = 1; i <= n; i++) {if(per[i].dir == 1) {if(per[i].x - 1.0 * (per[i].v + s) * val >= 0)continue;f1 = 1;if(per[i].x - 1.0 * per[i].v * val <= 0.0) {l1 = 0,l2 = 1e6;continue;}double t = (per[i].x - 1.0 * per[i].v * val) / s;ll dx = (ll) (per[i].x + floor((s - per[i].v) * (val - t)));l1 = min(l1,(ll)per[i].x);l2 = max(l2,dx);} else {if(per[i].x + 1.0 * (per[i].v + s) * val <= 1e6)continue;f2 = 1;if(per[i].x + 1.0 * per[i].v * val >= 1e6) {r1 = 0,r2 = 1e6;continue;}double t = (1e6 - per[i].x - 1.0 * per[i].v * val) / s;ll dx = (ll)(per[i].x - floor((s - per[i].v) * (val - t)));r1 = min(r1,dx);r2 = max(r2,(ll)per[i].x);}}if(!(f1 && f2))return false;if(l1 > l2 || r1 > r2)return false;return !(l1 > r2 || l2 < r1);}int main() {while(~scanf("%d %d",&n,&s)) {for(int i = 1; i <= n; i++) {scanf("%d %d %d",&per[i].x,&per[i].v,&per[i].dir);}double l = 0,r = 1e6,mid,ans = -1;for(int i = 1; i <= 50; i++) {mid = (l + r) / 2.0;if(solve(mid)) {r = mid;ans = mid;} else {l = mid;}}printf("%.7f\n",ans);}return 0;}

原创粉丝点击