數學:三分法


這里給出一個例題BZOJ1857,題意是這樣的:

在一個2維平面上有兩條傳送帶,每一條傳送帶可以看成是一條線段。兩條傳送帶分別為線段AB和線段CD。

lxhgww在AB上的移動速度為P,在CD上的移動速度為Q,在平面上的移動速度R。

現在lxhgww想從A點走到D點,他想知道最少需要走多長時間

根據肯定知道最終的路徑是一個這樣形狀的

關鍵就在於確定E和F點的位置

確定的時候控制變量,定E求F,定F求E

假設我們是定E求F,那么在AB上肯定存在一個點滿足AF+FE最小

在這個最值點的左右兩側都不能得到最優的結果

如果把這個距離值反饋成函數那么它就是一個單峰函數

然后我們只要求這個機制就好了,方法就是三分法,下面給出介紹:

 對於任意一個上凸函數,選取函數上任意兩個點A,B(xA<xB),若滿足yA<yB,那么該函數的極值點必然在[xA,+∞)中,若滿足yA>yB,那么該函數極值點必然在(-∞,xB]中,若滿足yA=yB,那么該函數的極值點必然在[xA,xB]中。

 對於任意一個下凸函數,選取函數上任意兩個點A,B(xA<xB),若滿足yA<yB,那么該函數的極值點必然在(-∞,xB]中,若滿足yA>yB,那么該函數極值點必然在[xA,+∞)中,若滿足yA=yB,那么該函數的極值點必然在[xA,xB]中。

然后用這個寫程序就好了。

 1 #include<cstdio>
 2 #include<cmath> 
 3 #define eps 1e-3
 4 int ax,ay,bx,by;
 5 int cx,cy,dx,dy;
 6 int p,q,r;
 7 inline int read()
 8 {
 9     int x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
12     return x*f;
13 }
14 double dis(double x1,double y1,double x2,double y2)
15 {
16     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
17 }
18 double cal(double x,double y)  //x和y是計算完的AB上的點 
19 {
20     double lx=cx,ly=cy,rx=dx,ry=dy;
21     double x1,y1,x2,y2,t1,t2;
22     while(fabs(rx-lx)>eps||fabs(ry-ly)>eps)
23     {
24         x1=lx+(rx-lx)/3;y1=ly+(ry-ly)/3;
25         x2=lx+(rx-lx)/3*2;y2=ly+(ry-ly)/3*2;
26         t1=dis(ax,ay,x,y)/p+dis(x,y,x1,y1)/r+dis(x1,y1,dx,dy)/q;
27         t2=dis(ax,ay,x,y)/p+dis(x,y,x2,y2)/r+dis(x2,y2,dx,dy)/q;
28         if(t1>t2){lx=x1;ly=y1;}
29         else {rx=x2;ry=y2;}
30     }
31     //計算完lx和ly是CD上的點 
32     return  dis(ax,ay,x,y)/p+dis(x,y,lx,ly)/r+dis(lx,ly,dx,dy)/q;
33 }
34 int main()
35 {
36     ax=read(),ay=read(),bx=read(),by=read();
37     cx=read(),cy=read(),dx=read(),dy=read();
38     p=read(),q=read(),r=read();
39     
40     double lx=ax,ly=ay,rx=bx,ry=by;
41     double x1,y1,x2,y2,t1,t2;
42     while(fabs(rx-lx)>eps||fabs(ry-ly)>eps)
43     {
44         x1=lx+(rx-lx)/3;y1=ly+(ry-ly)/3;
45         x2=lx+(rx-lx)/3*2;y2=ly+(ry-ly)/3*2;
46         t1=cal(x1,y1);t2=cal(x2,y2);  //用CD結果迭代算AB 
47         if(t1>t2) {lx=x1;ly=y1;}
48         else {rx=x2;ry=y2;}
49     }
50     printf("%.2lf\n",cal(lx,ly));
51     //傳AB終值算答案 
52     return 0;
53 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM