题目思路
本题要求我们求出车的最大速度值最小。像求 最大值最小
、最小值最大
这种类型的题目,我们很自然地就能想到用二分答案
(一般情况)来求解。
做二分题目时,我们要弄清楚这样几点:
-
二分什么
-
如何判断是否可行 ( 即check函数的内容 )
-
当二分到一个满足条件的解时,L , R 该如何移动
针对以上三个问题,我们来一步一步解决。
S1. 题目求速度,所以我们可以直接二分最大速度的值
S2. 在check函数中可以直接进行模拟送包裹,在模拟过程当中进行 判断(具体见代码)
S3. 可能我们做二分题目会形成了思维定式,例如求最 大/小 值解的时候,若 mid 满足题意,则就将 L=mid+1 或将 R=mid−1然而,由于此题考虑到精度问题,如果按照上述操作,那么我们就会错过 1/0.01=100(及以上)个可能满足条件的解 (保留两位小数)。
但是呢,就因为这句话
仅包括一个正数,为车的最大速度最小值,结果保留两位小数。
二分内就变成了......
l=0,r=1e9;
while(r-l>=0.00001)
{
mid=(l+r)/2;
if(check(mid))
{
res=mid;
r=mid;
}
else
{
l=mid;
}
}
因为两个小数几乎(不是不可能)不会相等。
另外有几个坑需要注意一下:
1、数据类型必须用long double,否则无法AC
2、精度必须精确到0.00001以下,否则会出现部分点过不去的情况
哦,还有check函数
bool check(double k)
{
long double sum=0; //sum记录进行时间
for(int i=1;i<=N;i++)
{
sum+=s[i]/k; //加上到达下个地点的时间
if(sum>y[i])
{
return false;
// 若超出签收时间右端点(即来晚了),说明以此速度不可行,直接返回false
}
if(sum<x[i])
{
sum=x[i]; // 如果小于签收时间左端点(即来早了),则等待至签收时间
}
}
return true; //若至始至终没有迟到,则说明以此速度的方案可行
}
都给这么多提示了,两块合起来就可以了,附上我的代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int x[maxn],y[maxn];
int s[maxn],N;
long double res;
bool check(double k)
{
long double sum=0;//sum记录进行时间
for(int i=1;i<=N;i++)
{
sum+=s[i]/k;//加上到达下个地点的时间
if(sum>y[i])
{
return false;//若超出签收时间(即来晚了),说明以此速度不可行,直接返回false
}
if(sum<x[i])
{
sum=x[i];//如果小于签收时间(即来早了),则等待至签收时间
}
}
return true;//若至始至终没有超出签收时间,则说明以此速度的方案可行
}
int main()
{
cin>>N;
for(int i=1;i<=N;i++)
{
cin>>x[i]>>y[i]>>s[i];
}
long double l=0,r=1e9,mid;
while(r-l>=0.00001)//二分控制精度
{
mid=(l+r)/2;
if(check(mid))
{
res=mid;
r=mid;
}
else
{
l=mid;
}
}
cout<<fixed<<setprecision(2)<<res;//保留两位小数
return 0;
}