2019 Multi-University Training Contest 1:Vacation(思维)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6581

在这里插入图片描述
题目大意:单行道上在tom的车前面有 n辆车,每辆车有一个速度和车长,以及它们车头到终点的距离,因为有的车快有的车慢,最终车会挨在一起,如果两车挨在一起,那么后面的车速度会慢下来跟前面的车一样快,多辆车挨在一起也是同理。问tom的车的车头过终点线的时间是多少。

分析:由于多辆车合并在一起,后面的车的速度会受影响,但车头是不受影响的,车头仍然按自己的速度在跑。最后tom的车一定是接在某辆车的后面越过终点(也可以没接在某辆车后面,这种情况可以当成接在自己后面)。车头不受影响,可以枚举车头是哪个,然后计算tom的车过终点的时间,取最大值。因为最后一定是跟着某辆车通过终点,如果你枚举的车头实际上在tom过终点之前都不能和这辆车合并,那么算出来的tom过终点的时间一定是缩短了,因此取最大值得出的是正解而且不会遗漏解。

#include<iostream>
using namespace std;
#include<stdio.h>
#include<string.h>
#include<queue>
int t,n;
const int maxn = 1e5 + 10;
double s[maxn],l[maxn],v[maxn];
int p[maxn],d[maxn],num[maxn];
int main() {
	while(~scanf("%d",&n)) {
		for(int i = 0; i <= n; i++)
			scanf("%lf",&l[i]);
		for(int i = 0; i <= n; i++)
			scanf("%lf",&s[i]);
		for(int i = 0; i <= n; i++)
			scanf("%lf",&v[i]);		
		double ans = 0,tmp = l[0];
		for(int i = 0; i <= n; i++) {
			if(i)
				l[i] += l[i - 1];
			ans = max(ans,(s[i] + l[i] - tmp) / v[i]);
		}
		printf("%.11lf\n",ans);
 	}
	return 0;
}

由于答案具有单调性:时间越长,tom越可能越过终点,可以二分时间,然后从后往前计算每辆车的所在的位置,判断一下tom的车的位置是否越过了终点。

#include<iostream>
using namespace std;
#include<stdio.h>
#include<string.h>
#include<queue>
int t,n;
const int maxn = 1e5 + 10;
const double eps = 1e-11;
double s[maxn],l[maxn],v[maxn];
int p[maxn],d[maxn],num[maxn];
double find() {
	double li = 0,ri = 1e9 + 1;
	while(ri - li > eps) {
		double mid = (li + ri) / 2;
		double lastpos;
		for(int i = n; i >= 0; i--) {
			if(i == n || s[i] - v[i] * mid > lastpos + l[i + 1]) 
				lastpos = s[i] - v[i] * mid; 
			else lastpos += l[i + 1];
		}
		if(lastpos <= 0)
			ri = mid;
		else li = mid + eps;
	}
	return li;
}
int main() {
	while(~scanf("%d",&n)) {
		for(int i = 0; i <= n; i++)
			scanf("%lf",&l[i]);
		for(int i = 0; i <= n; i++)
			scanf("%lf",&s[i]);
		for(int i = 0; i <= n; i++)
			scanf("%lf",&v[i]);		
		double ans = find();
		printf("%.11lf\n",ans);
 	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值