【來源】
一本通題庫-1435
LibreOJ-10013
vjudge
【題目描述】
明明做作業的時候遇到了 個二次函數 ,他突發奇想設計了一個新的函數 。
明明現在想求這個函數在 的最小值,要求精確到小數點後四位,四捨五入。
【輸入格式】
輸入包含 組數據,每組第一行一個整數 ;
接下來 行,每行 個整數 ,用來表示每個二次函數的 個係數。注意:二次函數有可能退化成一次。
【輸出格式】
每組數據輸出一行,表示新函數 的在區間 上的最小值。精確到小數點後四位,四捨五入。
【樣例輸入】
2
1
2 0 0
2
2 0 0
2 -4 2
【樣例輸出】
0.0000
0.5000
【數據範圍】
對於 的數據,;
對於 的數據,。
【解析】
三分。
三分法是在二分查找的基礎上,在右區間(或左區間)再進行一次二分。
與二分查找不同的是,三分法所面向的搜索序列的要求是:序列爲一個凸性函數。通俗來講,就是該序列必須有一個最大值(或最小值),在最大值(最小值)的左側序列,必須滿足不嚴格單調遞增(遞減),右側序列必須滿足不嚴格單調遞減(遞增)。
首先把 l-r 這個區間分成三部分(lmid和rmid)。
接下來就是判斷,我們因爲要求最小值,所以我們要使得左邊的值儘可能的小,這樣最左邊就是最小的。
接下來就是判斷最大值,就是找出lmid和rmid判斷出來的最大值,判斷如果lmid的最大值大於rmid,那就說明當前的隊列不是左邊最小,就把l移到lmid的位置,跳過不符合的那一段。如果小於,那就把r移到rmid的位置,在更左邊尋找。
經過這一循環的運算之後,我們就可以得到一個遞增的序列,而這個序列的最左邊就是最小值。
答案:判斷出l的值就好了。
細節:精度要開小,我開了1e-12。
【代碼】
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
const int N=1e5+5;
const int inf=2e9;
int n,T;
double a[N],b[N],c[N];
double calc(double x) {
double ret=-inf;
for(int i=1; i<=n; i++)
ret=MAX(ret,a[i]*x*x+b[i]*x+c[i]);
return ret;
}
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%lf%lf%lf",&a[i],&b[i],&c[i]);
double l=0,r=1000;
while(r-l>1e-12) {
double lmid=l+(r-l)/3.0;
double rmid=r-(r-l)/3.0;
if(calc(lmid)<=calc(rmid)) r=rmid;
else l=lmid;
}
double ans=calc(l);
printf("%0.4lf\n",ans);
}
return 0;
}