对比于二分法,三分法的适用范围要略窄一些,但是并不是代表它没有用,在一些题目中还是有很大用处的。。。
三分法是用来求一个凸性函数的方法,所谓凸性函数就是一个函数在某一区间内有最大值,最大值两侧各具有单调性,并且单调性相反。
题目大意:
给出一个N次函数,保证在范围[l,r]内存在一点x,使得[l,x]上单调增,[x,r]上单调减。试求出x的值
输入格式:
第一行一次包含一个正整数N和两个实数l、r,含义如题目描述所示
第二行包含N+1个实数,从高到低依次表示该N次函数各项的系数
输出格式:
输出为一行,包含一个实数,即为x的值。四舍五入保留5位小数。
首先,我们先求出l和r的中点mid,再求出mid和r的中点midd,分别将mid和midd代入式子,判断那个值大,舍弃值小的一段区间[l,mid]或[midd,r],然后接着三分直到找到答案为止。正确性还是比较显然的,如果mid与midd同侧,那么显然大的值更靠近x,如果异侧也是同理的(当然我们是无法知道同侧还是异侧的。。。)
最后,附上本题代码:
1 #include<cstdio> 2 #define maxn 13 3 using namespace std; 4 5 const double eps=1e-8; 6 int n; 7 double a[maxn+5]; 8 double l,r; 9 10 double check(double x) 11 { 12 double ans=a[n+1]; 13 for(int i=n; i>=1; i--) 14 { 15 double temp=a[n-i+1]; 16 for(int j=1; j<=i; j++) 17 { 18 temp*=x; 19 } 20 ans+=temp; 21 } 22 return ans; 23 } 24 int main() 25 { 26 scanf("%d%lf%lf",&n,&l,&r); 27 for(int i=1; i<=n+1; i++) 28 { 29 scanf("%lf",&a[i]); 30 } 31 while(r-l>eps) 32 { 33 double mid=(r+l)/2,midd=(mid+r)/2; 34 if(check(mid)>check(midd)) 35 { 36 r=midd; 37 } 38 else 39 { 40 l=mid; 41 } 42 } 43 printf("%.5lf",l); 44 return 0; 45 }