對於二分,相信你一定十分熟悉。就是在乙個具有單調性序列上查詢你所需要的數字。由於其單調性,你每一次在查詢是就可以將規模縮小一半,大致就是:
1.假設這個數列單調遞增
2.維護乙個區間左端點l
ll,區間右端點r和中間點mid
midmi
d3.如果mid
midmi
d比想要的值小,則左邊肯定不可以,那麼l=m
idl=mid
l=mi
d2.如果mid
midmi
d比想要的值大,則右邊肯定不可以,那麼r=m
idr=mid
r=mi
d因此大致就可以這麼寫:
while
(l+1
不保證**正確,但是具體思想就是這樣。
三分也一樣啊:
對於一段拋物線(極值的一邊單調遞增,極值的一邊單調遞減)我們就可以把它分成三段,根據其影象特性來求解。
對於三分,我們用左端點lmi
dlmid
lmid
和r mi
drmid
rmid
進行維護,將這個影象分成三段。並且影象區間的左右端點分別是l
ll則我們可以選擇這麼考慮:(以二次函式y=−
5x2+
8x−1
y=-5x^+8x-1
y=−5x2
+8x−
1為例)
如圖所示:
當l mi
dlmid
lmid
處於a
aa點,rmi
drmid
rmid
處於b
bb點時:可將左端點l
ll縮到lmi
dlmid
lmid
,右端點不變以保證極值存在。
當l mi
dlmid
lmid
處於a
aa點,rmi
drmid
rmid
處於c
cc點時:照樣可以將l
ll縮到lmi
dlmid
lmid
。同理,
當l mi
dlmid
lmid
處於c
cc點,rmi
drmid
rmid
處於d
dd點時:可將右端點r
rr縮到rmi
drmid
rmid
,左端點不變以保證極值存在。
當l mi
dlmid
lmid
處於b
bb點,rmi
drmid
rmid
處於b
bb點時:照樣可以將r
rr縮到rmi
drmid
rmid
。故得到結論:
f (l
)r)→l
=lmi
df(l)f(
l)r)→l
=lmidf(
l)≥f
(r)→
r=rm
idf(l)≥f(r)→r=rmid
f(l)≥f
(r)→
r=rm
id然後就進行簡單的**實現:
#include
using
namespace std;
double a,b,c;
inline
doublef(
double x)
intmain
(void)
cout<<
"x="
<
'\n'
; cout<<
"y="
<<
f(l)
;}通過畫圖和分類討論a
<
0a<0
a<
0的情況,不難得出:
f (l
)>f(
r)→l
=lmi
df(l)>f(r)→l=lmid
f(l)>f
(r)→
l=lm
idf (l
)≤f(
r)→r
=rmi
df(l)≤f(r)→r=rmid
f(l)≤f
(r)→
r=rm
id**實現只要if內反一下即可:
#include
using
namespace std;
double a,b,c;
inline
doublef(
double x)
intmain
(void)
cout<<
"x="
<
'\n'
; cout<<
"y="
<<
f(l)
;}如果需要高次函式過其它影象,只要在f內稍作修改即可。
三分法解決凸(凹)函式極值問題
二分法只適用與線性函式,當函式脫離線性而呈現凸性或者凹性的時候,三分是很有必要的。三分過程如下圖 凸函式 凹函式 實現方法 double calc double p double solve double min,double max return mid area 例題 hdu4355 party...
三分法(洛谷3382 模板 三分法)
如題,給出乙個n次函式,保證在範圍 l,r 內存在一點x,使得 l,x 上單調增,x,r 上單調減。試求出x的值。輸入格式 第一行一次包含乙個正整數n和兩個實數l r,含義如題目描述所示。第二行包含n 1個實數,從高到低依次表示該n次函式各項的係數。輸出格式 輸出為一行,包含乙個實數,即為x的值。四...
三分法小結
二分法作為分治中最常見的方法,適用於單調函式,逼近求解某點的值。但當函式是凸性函式時,二分法就無法適用,這時三分法就可以 大顯身手 如圖,類似二分的定義left和right,mid left right 2,midmid mid right 2 如果mid靠近極值點,則right midmid 否則...