https://www.luogu.org/problemnew/show/P1258(题目传送)
看题的第一眼就把题归为二分题,一直向着二分的方向走,却忽略了数学的推理。推理一番后(看了题解),发现原来如此简单。
由题意知,若要二人一起到达B点时耗时相同且最短,则二人走的路程、坐车的路程以及走和坐车的时间相同,并且车只能回接一次。设人走的路程为x、时间为t1,坐车的时间为t2,车返回接另一个人所用时间为t3,总共人的耗时为t,则t1=x/a,t2=(s-x)/b,t3=(s-2x)/b;
t2+t3=t=(2s-3x)/b=x/a,解得x=2as/(3a+b) 故轻松地用数学解出此题。
数学AC代码:
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
double s,a,b;
cin>>s>>a>>b;
double x=(*a*s)/(*a+b);
printf("%.6lf",x/a+(s-x)/b);
return ;
}
既然是个二分题,当然也可以用二分做了。我们可以二分车回接另一个人时的位置,算出若在此位置车回接,二人到终点分别的总耗时t1、t2,若t1==t2,输出答案(因为这里浮点数精度有误差,所以定义相等为差的绝对值小于一个非常小的数(这里题目要求误差小于1e-6,所以就把这个很小的数设为1e-6)),若t1>t2,使左端点等于mid,若t1<t2,则使右端点等于mid,直至有答案产生或两端点的差距小于1e-6为止。
二分AC代码:
#include<iostream>
#include<cstdio>
using namespace std;
double abs(double a)
{
return a>=?a:-a;
}
int main()
{
double s,a,b;
cin>>s>>a>>b;
double l=,r=s,mid=(l+r)/;
double t1=mid/b+(s-mid)/a,t2=(mid-mid/b*a)/(a+b)+mid/b+(s-((mid-mid/b*a)/(a+b)+mid/b)*a)/b;
while(r-l>=0.0000001)
{
if(abs(t1-t2)<0.000001)
break;
else
{
if(t1>t2)
l=mid;
else
r=mid;
}
mid=(l+r)/;
t1=mid/b+(s-mid)/a,t2=(mid-mid/b*a)/(a+b)+mid/b+(s-((mid-mid/b*a)/(a+b)+mid/b)*a)/b;
}
printf("%.6lf",t1);
return ;
}
为什么要发这么一个普及难度的题呢,因为是为了提醒以后数学与信息学的联系越来越深了