啵啵(*  ̄3)(ε ̄ *)根本不会三分啊,借此机会学一学喽!
粘贴一下来自oiwiki的三分法喽 https://oiwiki.com/basic/binary/#三分法
基本步骤(求极小值)
假设函数 f(x) 在区间 [l,r] 上单峰:
-
找两个三分点:m1=l+(r-l)/3; m2=r-(r-l)/3;
-
比较 f(m1) 和 f(m2):如果 f(m1) < f(m2) → 最小值在 [l, m2] → r = m2;否则 → 最小值在 [m1, r] → l = m1
-
重复上述步骤 → 区间越来越小 → 收敛到极小值
浅谈这道题三分的合理性:
莫非就是需要做到在s固定的时候,T是关于t在[0,1]上的单峰函数;在t固定的时候,T是关于s在[0,1]上的单峰函数,这两个很对称,此篇略证前者。
简化一下:公路长度 d,在公路上走的距离 td,比例 t∈[0,1],终点(指的是走了AB和平面,到达距离D有(1-s)CD的那个点)距离起点水平距离x,垂直距离h,都是定值,其中公路速度 p,平面速度 r
那么时间函数为
需要证明是单峰的,,,那要证明它二阶导大于0
因此 T(t) 在给定区间是严格凸函数,即是单峰的。
终于开始写代码了啵啵啵啵啵啵~~~
#include <bits/stdc++.h>using namespace std;double xA,yA,xB,yB,xC,yC,xD,yD,p,q,r;// :( 鬼知道为什么double y1过不了编译器,还非要换成字母累死人了
//距离函数
double dist(double x1,double y1,double x2,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}
//总时间函数
计算总时间:
A→E:长度 = t*AB,速度 = p → 时间 = t*AB/p
E→F:长度 = EF,速度 = r → 时间 = EF/r
F→D:长度 = (1-s)*CD,速度 = q → 时间 = (1-s)*CD/q
double time(double t,double s){
double Ex=xA+t*(xB-xA),Ey=yA+t*(yB-yA);
double Fx=xC+s*(xD-xC),Fy=yC+s*(yD-yC);
double AB=dist(xA,yA,xB,yB);
double CD=dist(xC,yC,xD,yD);
double EF=dist(Ex,Ey,Fx,Fy);
return t*AB/p+EF/r+(1-s)*CD/q;
}
//内层三分函数(主打一个t固定了,再去找最优的s
double find(double t){double l=0,r=1;
for(int i=0;i<100;i++){
double m1=l+(r-l)/3;//左三分
double m2=r-(r-l)/3;//右三分点
if(time(t,m1)<time(t,m2)) r=m2;
else l=m1;
}
return time(t,l);
}
//主函数部分,for循环进行外层三分,找最优的t
int main(){cin>>xA>>yA>>xB>>yB>>xC>>yC>>xD>>yD>>p>>q>>r;
double l=0,r=1,ans=1e18;
for(int i=0;i<100;i++){
double m1=l+(r-l)/3;
double m2=r-(r-l)/3;
double f1=find(m1);
double f2=find(m2);
if(f1<f2) r=m2;
else l=m1;
}
ans=find(l);
printf("%.2f\n",ans);
return 0;
}
综上所述,来一份完整代码吧:
#include <bits/stdc++.h>using namespace std;double xA,yA,xB,yB,xC,yC,xD,yD,p,q,r;double dist(double x1,double y1,double x2,double y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}double time(double t,double s){double Ex=xA+t*(xB-xA),Ey=yA+t*(yB-yA);double Fx=xC+s*(xD-xC),Fy=yC+s*(yD-yC);double AB=dist(xA,yA,xB,yB);double CD=dist(xC,yC,xD,yD);double EF=dist(Ex,Ey,Fx,Fy);return t*AB/p+EF/r+(1-s)*CD/q;}double find(double t){double l=0,r=1;for(int i=0;i<100;i++){double m1=l+(r-l)/3;double m2=r-(r-l)/3;if(time(t,m1)<time(t,m2)) r=m2;else l=m1;}return time(t,l);}int main(){cin>>xA>>yA>>xB>>yB>>xC>>yC>>xD>>yD>>p>>q>>r;double l=0,r=1,ans=1e18;for(int i=0;i<100;i++){double m1=l+(r-l)/3;double m2=r-(r-l)/3;double f1=find(m1);double f2=find(m2);if(f1<f2) r=m2;else l=m1;}ans=find(l);printf("%.2f\n",ans);return 0;}

京公网安备 11010502036488号