算法标签:二分、模拟
*备注:本题难度属于“提高/普及+”,难度稍大。
题目描述:
小 K 成功地破解了密文。但是乘车到 X 国的时候,发现钱包被偷了,于是无奈之下只好作快递员来攒足路费去 Orz 教主……
一个快递公司要将 n 个包裹分别送到 n 个地方,并分配给邮递员小 K 一个事先设定好的路线,小 K 需要开车按照路线给的地点顺序相继送达,且不能遗漏一个地点。小 K 得到每个地方可以签收的时间段,并且也知道路线中一个地方到下一个地方的距离。若到达某一个地方的时间早于可以签收的时间段,则必须在这个地方停留至可以签收,但不能晚于签收的时间段,可以认为签收的过程是瞬间完成的。
为了节省燃料,小 K 希望在全部送达的情况下,车的最大速度越小越好,就找到了你给他设计一种方案,并求出车的最大速度最小是多少。
输入格式:
第 1 行为一个正整数 n,表示需要运送包裹的地点数。
下面 n 行,第 i+1 行有 3 个正整数 Xi,Yi,Si,表示按路线顺序给出第 i 个地点签收包裹的时间段为 [Xi,Yi],即最早为距出发时刻 Xi,最晚为距出发时刻 Yi,从前一个地点到达第i 个地点距离为 Si,且保证路线中 Xi 递增。
可以认为 S1 为出发的地方到第 1 个地点的距离,且出发时刻为 0。
输出格式:
仅包括一个正数,为车的最大速度最小值,结果保留两位小数。
输入输出样例:
输入1#: 输出1#:
3 2.00 1 2 2 6 6 2 7 8 4
说明:
结果保留两位小数。
样例解释:
第一段用 1的速度在时间 2 到达第 1 个地点,第二段用 0.5 的速度在时间 6 到达第 2 个地点,第三段用 2 的速度在时间 8 到达第 3个地点。
——————————————————————————————————————————
分析题目:
1.要求的是最大速度的最小值
2.当我们到达一个地点的时候,还没到这个地点的签货时间,可以等到地点签货时间开始了再走
3.xi单调递增
很明显,我们可以全程保持着最大速度,这样可以更加的有机会抵达后面的,签货地点。
而且如果当速度为v的时候,可以抵达所以签货地点,那么当速度为(v+x)的时候,也可以抵达所有地点。所以这个问题是有单调性的,可以二分答案。具体细节看代码注释。
代码CODE:
#include <bits/stdc++.h>
#define double long double
using namespace std;
struct oi{
double x,y,s;
}a[2000001];
int n;
bool check(double v){
double t=0;
for(int i=1; i<=n; i++){
t=t+(double)(a[i].s)/(double)(v); //计算到下一个地方的最早的时间
if(t>a[i].y) {//如果全程保持最大速度还来晚了,那就直接return 0;
return 0;
}
if(t<a[i].x){//如果来早了,那就等到可以开始签收的时间再走
t=a[i].x;
}
}
return 1;
}
int main(){
cin>>n;
for(int i=1; i<=n; i++) scanf("%LF%LF%LF",&a[i].x,&a[i].y,&a[i].s);
double l=0,r=2e9;//二分速度
while(l<=r){
double mid=(l+r)/2;
if(check(mid)){//如果当前速度有解,那么所有速度大于当前速度的数值就都有解,直接放弃那些数值,搜比当前数值更小的数值 所以是r=mid-(derla)
r=mid-0.00001;
} else l=mid+0.000001;
}
printf("%0.2LF",l);
return 0;
}
PWP
博客介绍了如何使用C++通过二分法和模拟解决快递包裹配送问题,找到在确保所有包裹送达情况下,最小的最大速度。文章包含题目描述、输入输出格式、样例解析及算法分析,强调了问题的单调性并提供了代码实现。
1536

被折叠的 条评论
为什么被折叠?



