C - Line belt HDU - 3400(三分与精度问题)

xiaoxiao2021-02-28  100

这是一道求二元函数极小值的问题,采用的是控制一个变量,然后取找另外一个变量的对应的最小值. 三分套一个三分, 后来队友说二分也可以解决(不考虑精度的话), 仔细想想却是也是对的,只是写起来比三分稍复杂 一些. 先二分最小值,再二分一个x,在二分是否存在y….. 这里卡了精度, 对于计算sqrt()时,存在很大的误差,给其加上eps以保证前9位都是正确的.

#include<cstdio> #include<iostream> #include<cmath> const double eps = 1e-9; using namespace std; struct Point{ double x,y; }a,b,c,d,t1,t2; double ab,cd,p,q,r; double dis(Point &a, Point &b){ return eps+sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y) ); } double slove(double t){ t2.x = d.x + (c.x - d.x)/cd*t*q; t2.y = d.y + (c.y - d.y)/cd*t*q; return t+dis(t1,t2)/r; } double cal(double t){ t1.x = a.x + (b.x - a.x)/ab*t*p; t1.y = a.y + (b.y - a.y)/ab*t*p; double l = 0, r = cd/q, mid1, mid2; for(int i = 0; i < 300; i++){ mid1 = l + (r - l)/3; mid2 = r - (r - l)/3; if(slove(mid1) < slove(mid2))r = mid2; else l = mid1; } return t+slove(l); }; int main(){ int t = 0;scanf("%d",&t); while(t--){ scanf("%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y); scanf("%lf%lf%lf%lf", &c.x, &c.y, &d.x, &d.y); scanf("%lf%lf%lf", &p, &q, &r); ab = dis(a,b), cd = dis(d, c); double l = 0, r = ab/p, mid1, mid2; for(int i = 0; i < 300; i++){ mid1 = l + (r - l)/3; mid2 = r - (r - l)/3; if(cal(mid1) < cal(mid2)){ r = mid2; }else{ l = mid1; } } printf("%.2lf\n",cal(l)); } return 0; }
转载请注明原文地址: https://www.6miu.com/read-40959.html

最新回复(0)