P1883 题解
题目传送门
样例解释
对于第 2 个样例,其
算法介绍
三分是由二分延伸出的一种算法。但与二分不同的是,二分可以解决答案具有单调性的问题,而三分可以解决单峰或者单谷问题。例如本题所给的二次函数,就是一个单谷函数。
函数需要用浮点类型结构实现,而常用的 double 等类型会误差。所以规定所允许的误差
然后进行三分,规定下界
正确性证明
更新
计算一次
代码实现
#include<bits/stdc++.h>
using namespace std;
int read(){int x=0;char f=1,ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int N=1e4+10;
const double EPS=1e-9;
int n,a[N],b[N],c[N];
double calc(double x,int p){ //计算二次函数 f(x)
return a[p]*x*x+b[p]*x+c[p];
}
double f(double x){ //求最大值 F(x)
double res=-1e18;
for(int i=1;i<=n;++i)
res=max(res,calc(x,i));
return res;
}
void solve(){
n=read();
for(int i=1;i<=n;++i)
a[i]=read(),b[i]=read(),c[i]=read();
double l=0,r=1000; //已知 F(x) 在区间 [0,1000] 内
while(r-l>EPS){
double lmid=l+(r-l)/3,rmid=r-(r-l)/3.0; //两个中间点
if(f(lmid)<f(rmid)) //M1 更贴近答案
r=rmid; //舍去区间 (M2,R]
else l=lmid; //舍去区间 [L,M1)
}
printf("%.4lf\n",f(l)); //最终输出的是 F(x) 的最小值
return;
}
int main(){
int T=read();
while(T--)
solve();
return 0;
}
可以做做 P3382 练练手。