铜牌题 Walker(三分+分类讨论)

题目链接:https://ac.nowcoder.com/acm/contest/9925/D

可以分以下几种情况:
①两个人中选一个走完全程
②互相向对面走,走到边界,算两者时间久的那个
③将两人中间某点作为划分点,两个人分别负责走自己的部分

主要是第三点,如果只考虑分类就只能想到一些个别的情况。
实际上两人中间的位置,任意点都可能作为划分点,所以需要用三分。注意一个人走自己的部分有两种走法,选时间最少的那种。

#include <bits/stdc++.h>
using namespace std;

double n;
struct Node {
	double pos, v;
}p[2];

double cal(double x) {
	double t1 = min((2.0 * x - p[0].pos) / p[0].v, (p[0].pos + x) / p[0].v);
	double t2 = min((n + p[1].pos - 2.0 * x) / p[1].v, (2 * (n - p[1].pos) + p[1].pos - x) / p[1].v);
	return max(t1, t2);
}

int main(void) {
//	freopen("in.txt", "r", stdin);
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%lf%lf%lf%lf%lf", &n, &p[0].pos, &p[0].v, &p[1].pos, &p[1].v);
		if (p[0].pos > p[1].pos) swap(p[0], p[1]);
		double ans = 1e18;
		// 只算一个人走 
		ans = min(ans, (p[0].pos + n) / p[0].v);
		ans = min(ans, (n + n - p[0].pos) / p[0].v);
		ans = min(ans, (p[1].pos + n) / p[1].v);
		ans = min(ans, (n + n - p[1].pos) / p[1].v);
		double t1, t2;
		// <-0 1->
		t1 = p[0].pos / p[0].v;
		t2 = (n - p[1].pos) / p[1].v;
		if (t1 < t2) {
			double pos1 = (t2 - t1) * p[0].v;
			if (n > pos1)
				ans = min(ans, t2 + (n - pos1) / (p[0].v + p[1].v));
		}
		else {
			double pos2 = n - (t1 - t2) * p[1].v;
			if (pos2 > 0)
				ans = min(ans, t1 + pos2 / (p[0].v + p[1].v));
		}
		// 0-> <-1直接走,不回头 
		ans = min(ans, max((n - p[0].pos) / p[0].v, p[1].pos / p[1].v));
		
		// 三分
		double l = p[0].pos, r = p[1].pos;
		while (l + 1e-6 < r) {
			double mid1 = l + (r - l) / 3;
			double mid2 = r - (r - l) / 3;
			double t1 = cal(mid1);
			double t2 = cal(mid2);
			if (t1 > t2) l = mid1;
			else r = mid2;
		}
		ans = min(ans, min(cal(l), cal(r)));
		printf("%.99f\n", ans);
	}	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JILIN.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值