三分算法
利用三分法求最值
parabolic curve.(抛物线)
题意
下凸抛物线每一个x处的最大值的最小值(这些最大值属于一条新的下凸抛物线)
个人理解:
三分的区间不一定需要从中间分,只要分出三个区间,判断 l, r 大小关系即可
1.
while(r-l > 1e-9) { // 以求下凸最小值为例
mid1 = (l+r)/2;
mid2 = (mid1+r)/2;
if(f(mid1) > f(mid2)) l = mid1;
else r = mid2;
}
while(r-l >= 1e-9) {
mid1 = l + (r-l)/3;
mid2 = r - (r-l)/3;
if(f(mid1) > f(mid2)) l = mid1;
else r = mid2;
}
题解
上凸函数能用三分法求最小值,不能用来求最大值
该题中最大值求法,遍历复杂度O(n),或者从抛物线最低点左右比对
复杂度分析
遍历求最大值 O(100n)
三分求最小值 O(2logm)
最终 O(100100002*log(1000)) == 2e7
这题纯暴力也能过
代码
#include<bits/stdc++.h>
using namespace std;
#define N 10005
double x, y, n;
double a[N], b[N], c[N];
double f(double x) {
double maxx = 0;
for(int i = 1; i <= n; i++) {
maxx = max(maxx, a[i]*x*x + b[i]*x + c[i]);
}
return maxx;
}
int main() {
freopen("test.in", "r", stdin);
int kase;
double mid1, mid2;
cin >> kase;
while(kase--) {
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i] >> b[i] >> c[i];
}
double l = 0, r = 10000;
while(r-l >= 1e-9) {
mid1 = l + (r-l)/3;
mid2 = r - (r-l)/3;
if(f(mid1) > f(mid2)) l = mid1;
else r = mid2;
}
printf("%.4f\n", f(l));
}
return 0;
}