C

来源:互联网 发布:网络有个感叹号怎么办 编辑:程序博客网 时间:2024/05/22 11:36

这是一道求二元函数极小值的问题,采用的是控制一个变量,然后取找另外一个变量的对应的最小值.
三分套一个三分, 后来队友说二分也可以解决(不考虑精度的话), 仔细想想却是也是对的,只是写起来比三分稍复杂 一些. 先二分最小值,再二分一个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;}
原创粉丝点击