三分·三分求极值 算法讲解和题目
题目:
#1142 : 三分·三分求极值
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
这一次我们就简单一点了,题目在此:
在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d。
输入
第1行:5个整数a,b,c,x,y。前三个数构成抛物线的参数,后两个数x,y表示P点坐标。-200≤a,b,c,x,y≤200
输出
第1行:1个实数d,保留3位小数(四舍五入)
- 样例输入
-
2 8 2 -2 6
- 样例输出
-
2.437
解题思路:
这道题,我们拿到手后都知道应该求 d = min(sqrt((X-x)^2+(Y-y)^2)), 那么我们知道了我们的目标函数后,我们就应该把这个函数来化简,化简后,我们知道这个函数是一个四次的函数,那么对于我们最为普通的求导求极值的方法来说,是根本不可能达到的。进一步观察题目,我们可以发现根据带入的X值不同,d的长度恰好满足凸形函数。
而我们要求的最短距离d,正好就是这个凸形函数的极值。
代码:
1 # include <cstdio> 2 # include <iostream> 3 # include <cmath> 4 using namespace std; 5 double a,b,c,X,Y; 6 double possible( double x ) 7 { 8 double y = a*x*x+b*x+c; 9 double res = hypot(X-x,Y-y); 10 return res; 11 } 12 int main(void) 13 { 14 cin>>a>>b>>c>>X>>Y; 15 double l = -233.0; 16 double r = 233.0; 17 while ( abs(r-l) > 1e-8 ) 18 { 19 double m1 = l+(r-l)/3; 20 double m2 = r-(r-l)/3; 21 if ( possible(m1) < possible(m2) ) 22 { 23 r = m2; 24 } 25 else 26 { 27 l = m1; 28 } 29 } 30 printf("%.3lf\n",(possible(l)+(possible(r)))/2); 31 32 33 return 0; 34 }