轉自:http://www.cnblogs.com/markliu/archive/2012/08/09/2630652.html
如圖,類似二分的定義Left和Right,mid = (Left + Right) / 2,midmid = (mid + Right) / 2; 如果mid靠近極值點,則Right = midmid;否則(即midmid靠近極值點),則Left = mid;
double Calc(Type a) { /* 根據題目的意思計算 */ } void Solve(void) { double Left, Right; double mid, midmid; double mid_value, midmid_value; Left = MIN; Right = MAX; while (Left + EPS < Right) { mid = (Left + Right) / 2; midmid = (mid + Right) / 2; mid_area = Calc(mid); midmid_area = Calc(midmid); // 假設求解最大極值. if (mid_area >= midmid_area) Right = midmid; else Left = mid; } printf("%.0lf\n",Calc(Left)); }
接下來看幾個例題:給出函數,其他的套模板就可以AC
hdu-4355 party all the time (2012 Multi-University Training Contest
6 )
函數爲:
double Calc(double i){ double S=0.0; for(int j=0;j<n;j++){ S+=fabs((i-p[j].x)*(i-p[j].x)*(i-p[j].x))*p[j].w; } return S; }
zju-3203 Light Bulb (The 6th Zhejiang Provincial Collegiate Programming Contest)
函數爲:
double Calc(double x){ return (h*D-H*x)/(D-x)+x; }
hdu-3714 Error Curves (2010 Asia Chengdu Regional Contest )
函數爲:
double Calc(double x){ double Max,t; Max=p[0].a*x*x+p[0].b*x+p[0].c; for(int i=1;i<n;i++){ t=p[i].a*x*x+p[i].b*x+p[i].c; Max=max(t,Max); } return Max; }
hdu-2438 Turn the corner (2008 Asia Harbin Regional Contest Online )
函數爲:
double Calc(double a) { double b,c,d; b=w/sin(a)+l*cos(a); c=l*sin(a)+w/cos(a)-x; d=l*sin(a)+w/cos(a); return c*b/d; }
這道題單純的套模板會WA,我們要將分割方向倒置,midmid=(mid+l)/2;從左邊取第二個中點。
double l,r,mid,midmid,mid_area,midmid_area; l=0.0,r=pi/2; while(l+eps<r){ mid=(l+r)/2; midmid=(mid+l)/2; mid_area=Calc(mid); midmid_area=Calc(midmid); if(mid_area>=midmid_area) l=midmid; else r=mid; }