標籤:idt blog inline scanf 存在 技術分享 get 三分 怎麼
二分與三分
(寫的很早忘了發布了...)今天高二的學長學姐們進行了二分和三分的測試(又名一本通課後題測試),感覺這個好有意思~
關於什麼是二分,三分,先咕咕咕了,來看一道題。
燈泡:https://loj.ac/problem/10016
題意概述:給出$H,h,D$,求陰影的最長長度(包括地上的和牆上的)。
有種初中數學的既視感。
解:設燈泡為$A$,人頭為$B$,串連$AB$並延長,與地面的延長線交於點$C$.
於是就結束了...嗎?
還有一種可能就是影子並沒有到牆上去,但是影響不大,兩個函數疊加起來還是單峰的,似乎就是那種對勾函數?
1 # include <cstdio> 2 # include <iostream> 3 4 using namespace std; 5 6 int T; 7 double H,h,d,a1,a2; 8 double ans,l,r,lmid,rmid; 9 10 double f (double x)11 {12 double ans=0,a,b;13 b=h*(d-x)/(H-h);14 if(b<=x)15 return b;16 ans+=x;17 a=(x*H-d*h)/(h-H);18 ans+=a*h/(x+a);19 return ans;20 }21 22 int main()23 {24 scanf("%d",&T);25 while (T--)26 {27 scanf("%lf%lf%lf",&H,&h,&d);28 l=0,r=d,ans=0;29 while (r-l>=0.0001)30 {31 lmid=l+(r-l)/3.0;32 rmid=r-(r-l)/3.0;33 a1=f(lmid);34 a2=f(rmid);35 if(f(lmid)<f(rmid))36 l=lmid;37 else 38 r=rmid;39 }40 printf("%.3lf\n",f(l));41 }42 return 0;43 }燈泡
迎風舞:https://www.cnblogs.com/shzr/p/9751719.html
傳送帶:https://www.luogu.org/problemnew/show/P2571
題意概述:給定平面上的兩條線段,在每條上移動的速度分別是$a$,$b$,也可以脫離線段到平面上走,同樣有一個速度$c$,求從第一條線段上的$A$點到另一條上的$D$點的最短距離.
首先想到的是貪心...如果平面上走的快就到面上去,如果線上更快就線上上走,然而這個顯然是錯的,因為有時雖然線上走的快,但是卻越走越偏?
最終的答案應該是在起始線段上走一段,再在平面上走一段到達終點線段,再在那條線段上一直走到終點.先考慮一個比較簡單的問題,如果只是平面上有一條線段,求從某個點到線段端點的最小距離怎麼做?列方程發現是一個二次函數,可以求出係數來求極值,也可以三分.現在考慮起始點不固定的情況:如果對於每個起始點都求出最小距離,可以視為一個關於起始點的函數.首先這個函數應該是連續的,所以要是想不明白上類比退火也行,顯然它不一定是單調的,但是應該也不是特別奇怪的形狀,嚴謹的證明其實我也不會,但是可以感受一下.最優解肯定是存在的,而且起始點越偏離最優解答案就越劣.為什麼?以下是胡亂證明,不保證正確:起始點移動一點,到達點也會相應的移動一些,在很小的範圍內這種移動可能是單調的,但是過了某一個點之後就會往反方向移動?
總之網上也沒找到好的證明,就這樣吧.
注意:有可能某一條線段退化成一個點,三分還沒開始就退出了...可以考慮換成控制三分次數的做法.
1 # include <cstdio> 2 # include <iostream> 3 # include <cmath> 4 # include <algorithm> 5 6 using namespace std; 7 8 const int maxn=300; 9 int ax,ay,bx,by;10 int cx,cy,dx,dy;11 double p,q,r;12 double la,lb,L,R,lmid,rmid;13 int cnt=maxn;14 15 inline double l (double len,double x,double y)16 {17 double ans=0,x_,y_;18 x_=cx,y_=cy;19 if(lb) x_=len*(dx-cx)/lb+cx;20 if(lb) y_=len*(dy-cy)/lb+cy;21 ans+=sqrt((x_-dx)*(x_-dx)+(y_-dy)*(y_-dy))/q;22 ans+=sqrt((x-x_)*(x-x_)+(y-y_)*(y-y_))/r;23 return ans; 24 }25 26 inline double f (double len)27 {28 double L=0,R=lb,lmid,rmid,x,y,l1;29 x=ax,y=ay;30 if(la) x=len*(bx-ax)/la+ax;31 if(la) y=len*(by-ay)/la+ay;32 l1=sqrt((x-ax)*(x-ax)+(y-ay)*(y-ay))/p;33 int cnt=maxn;34 while (cnt)35 {36 lmid=L+(R-L)/3.0;37 rmid=R-(R-L)/3.0;38 if(l(lmid,x,y)>l(rmid,x,y))39 L=lmid;40 else R=rmid;41 cnt--;42 }43 return l(L,x,y)+l1;44 }45 46 int main()47 {48 scanf("%d%d%d%d",&ax,&ay,&bx,&by);49 scanf("%d%d%d%d",&cx,&cy,&dx,&dy);50 scanf("%lf%lf%lf",&p,&q,&r);51 la=sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by));52 lb=sqrt((cx-dx)*(cx-dx)+(cy-dy)*(cy-dy));53 L=0,R=la;54 while (cnt)55 {56 lmid=L+(R-L)/3.0;57 rmid=R-(R-L)/3.0;58 if(f(lmid)>f(rmid))59 L=lmid;60 else R=rmid;61 cnt--;62 }63 printf("%.2lf",f(R));64 return 0;65 }傳送帶
---shzr
二分與三分