三分不熟悉的,可以看看李煜东的见解:



1.二分为什么不行
首先说明二分为什么不行

如上图,在找最小值的过程中,按二分的操作,极大可能会从区间[left,right]跨越到区间[mid,right],很明显,最小值丢了。
所以上,三分算法。
2.题目意图解释
该题题意也比较绕,
真实意图是:
如x只取三个值x1,x2,x3
在x1时,找出f1(x1),f2(x1),...,fn(x1),最大值y1
在x2时,找出f1(x2),f2(x2),...,fn(x2),最大值y2
在x3时,找出f1(x3),f2(x3),...,fn(x3),最大值y3
在y1,y2,y3中,再找出最小值y,输出y。
3.为什么在一堆单谷函数中找最大值,还是单谷函数,
我的理解是这样的:具体某个最大值还是依附于某个单谷函数,虽然,x值不同时,最大值依附于不同的单谷函数,但是都是单谷函数,最后最大值的形态应该也是单谷函数。也就是祖先是单谷函数,后代子孙也是单谷函数。
4.AC精度设置
//#define eps 0.000001//第一次提交,全WA
#define eps 1e-9//第二次提交,Subtask#1 WA
//double mx=-1000000,y;//第二次提交,Subtask#1 WA
double mx=-1e18,y;//第三次提交,彻底AC Subtask#1通过
AC代码如下
#include <bits/stdc++.h>
using namespace std;
//该函数是二次函数,可以采用二次函数求极值的办法,直接算出。
//求极值,奇次方,就是找两个边界即可
//求极值,偶次方,感觉可以退化到二次方,但想想又有牵绊,如x^4+x^3+x^2+x+1就不容易
//整数编惯了,小数还不会了。
//题意比较绕,编写过程中,才弄了明白,其中借助了几何画板
//为什么不能用二分,总算想通了。
//#define eps 0.000001//第一次提交,全WA
#define eps 1e-9//第二次提交,Subtask#1 WA
#define maxn 10010
int a[maxn],b[maxn],c[maxn];
double f(int a,int b,int c,double x){
return a*x*x+b*x+c;
}
double F(int n,double x){
//double mx=-1000000,y;//第二次提交,Subtask#1 WA
double mx=-1e18,y;//第三次提交,彻底AC Subtask#1通过
for(int i=1;i<=n;i++){
y=f(a[i],b[i],c[i],x);
if(mx<y)mx=y;
}
return mx;
}
double trisection(int n){
double lf,rt,lmid,rmid;//lf左边界,rt右边界
double s;
lf=0,rt=1000;
while(lf+eps<rt){
s=(rt-lf)/2;//退化为2分
lmid=lf+s;
rmid=rt-s;
if(F(n,lmid)>=F(n,rmid))lf=lmid;
else rt=rmid;
//printf("lf=%lf rt=%lf lmid=%lf rmid=%lf\n",lf,rt,lmid,rmid);
}
return lf;
}
int main(){
int T,n;
double x,mxf,fv;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
x=trisection(n);
printf("%.4lf\n",F(n,x));
}
}


被折叠的 条评论
为什么被折叠?



