手动插姿势:
三分法可以应用于凸函数或者凹函数的求极值。
三分讲解:http://blog.csdn.net/pi9nc/article/details/9666627
三分模板:http://www.cnblogs.com/Hilda/archive/2013/03/02/2939708.html
double cal(Type a)
{
/* 根据题目的意思计算 */
}
void solve()
{
double Left, Right;
double mid, midmid;
double mid_value, midmid_value;
Left = MIN; Right = MAX;
while (Left + EPS <= Right)
{
mid = (Left + Right) / 2;
midmid = (mid + Right) / 2;
if (cal(mid)>=cal(midmid))
Right = midmid;
else Left = mid;
}
}
更多相关题:
HDU :3400 2298 4454 2438 3756
POJ: 3301 3737
ZOJ: 3203
题意:
给n个二次函数,定义域为[0,1000], 求x在定义域中每个x所在的n个函数的最大值的最小值。
思路:
其实说N个函数的话,定义域也确定了,要么是单调增,要么是单调减,要么就是凹性,因为a>=0的,三分一下,每次找位置的最大,然后取最小就好了。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e4;
const double eps=1e-9;
const double INF=1e15;
struct asd{
double a,b,c;
};
asd q[N];
int n;
double fx(double a,double b,double c,double x)
{
return a*x*x+b*x+c;
}
double getmin(double x)
{
double temp;
double ans=-INF;
for(int i=0;i<n;i++)
{
temp=fx(q[i].a,q[i].b,q[i].c,x);
if(ans<temp)
ans=temp;
}
return ans;
}
void sanfen()
{
double ans=INF;
double Left, Right;
double mid;
double temp1,temp2;
Left = 0; Right = 1000;
while (Left<=Right)
{
mid=(Left+Right)/2;
temp1=getmin(mid);
temp2=getmin(mid-eps);
if(temp1<temp2)
Left=mid+eps;
else
Right=mid-eps;
if(ans>temp1)
ans=temp1;
}
printf("%.4lf
",ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf%lf",&q[i].a,&q[i].b,&q[i].c);
sanfen();
}
return 0;
}