LOJ#10013 曲线(三分)

题目链接

题目描述

明明做作业的时候遇到了 n 个二次函数 Si(x)=ax^2 + bx + c,他突发奇想设计了一个新的函数 F(x)=max⁡{Si(x)},i=1…n。

明明现在想求这个函数在 [0,1000] 的最小值,要求精确到小数点后四位,四舍五入。

输入格式

输入包含 T 组数据,每组第一行一个整数n;

接下来 n 行,每行 3 个整数 a, b, c ,用来表示每个二次函数的 3 个系数。注意:二次函数有可能退化成一次。

输出格式

每组数据输出一行,表示新函数 F(x) 的在区间 [0,1000] 上的最小值。精确到小数点后四位,四舍五入。

样例

样例输入

2
1
2 0 0
2
2 0 0
2 -4 2

样例输出

0.0000
0.5000

数据范围与提示

对于 50% 的数据,1≤n≤100;

对于 100% 的数据,1≤T≤10, 1≤n≤10^5, 0≤a≤100, 0≤∣b∣≤5000, 0≤∣c∣≤5000。

 

三分法适用于求解凸性函数的极值问题,二次函数就是一个典型的单峰函数。

设当前求解的区间为[l,r],令m_1=l+\frac{r-l}{3}m_2=r-\frac{r-l}{3},接着计算这两个点的函数值f(m_1)f(m_2)之后将两点中函数值更优的那个点称为“好点”(若计算最小值,则f更小的那个点就为好点),而函数值较差的那个点称为“坏点”。

可以利用反证法证明:最优点和好点在坏点的同侧

如图,f(m2)>f(m1),最大值为最优点,因此m1是坏点,m2是好点,最优点与m2会位于m1同侧,求解区间由[l,r]变为[m1,r]。由此可以不停缩小求解区间,直至得出近似解。

如果函数不严格单调,三分法将不适用。

 

由于a大于等于0,函数S是开口向上的二次函数(当a=0时是一次函数),即S为先单调递减,后单调递增的下凸函数,或者是一次单调函数,F(x)=max⁡{Si(x)}也满足单调性。因此可用三分法求解[0,1000]内的最小值。

AC代码:

CSDN博客:https://blog.csdn.net/qq_40889820
#include<iostream>
#include<sstream>
#include<algorithm>
#include<string>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define e 2.71828182
#define Pi 3.141592654
#define INF 1<<30
using namespace std;
struct node
{
    double a,b,c;	
}quad[10010];
int n;
double fun(double x)//F(x)
{
	double ans=-INF;
	for(int i=1;i<=n;i++)
	ans=max(ans,quad[i].a*x*x+quad[i].b*x+quad[i].c);
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);cout.tie(NULL);
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n;
		for(int i=1;i<=n;i++) cin>>quad[i].a>>quad[i].b>>quad[i].c;
		double l=0.0,r=1000.0;//[0,1000] 
		while(r-l>1e-11)
		{
			double mid1=l+(r-l)/3,mid2=r-(r-l)/3;
			if(fun(mid1)<fun(mid2))//mid1是好点
			r=mid2; 
			else l=mid1;
		}
		cout<<setiosflags(ios::fixed)<<setprecision(4)<<fun(l)<<endl;
	}
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值