hdu 3400 Line belt

来源:互联网 发布:天敏网络机顶盒刷机 编辑:程序博客网 时间:2024/05/17 17:41

先求一个点到  一条线段的最小值。

从P 到B .

 从 c 到 A  肯定是增加的 。

设 cd 为x ,cb 是 L2  pc 是L1

线段上 速率是 k2   其余为 k1

t = sqrt(L1*L1 + x*x )/k1  + (L1 -x);

求导。 

f = 2/(k1 * sqrt(L1 *L1  + x*x)) *x - 1/k2

随着x 的增大 f 逐渐变大。但是由于 k1 k2 不确定 所以 f 可能 由负 变成正 或者 只有正。

加上AC 同样 满足三分性质。

x = L1 /  sqrt( (4*K2*k2 - K1*K1)/ (K1*K1))

所以 x 跟 L1 成正比(重要)。

在根据 成正比 这个性质 很容易分析出 两条线的时候也是满足 三分性质的 (同样跟垂线有关 ,以此为分界线。趋近B端 的 变化成 以一定的比率上升 或下降 ,在加上A到垂足部分 就是可能 出现 下凸。 )

#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <stack>#include <cstring>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <ctime>#include <assert.h>#include <queue>#define REP(i,n) for(int i=0;i<n;i++)#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)#define ALLL(x) x.begin(),x.end()#define SORT(x) sort(ALLL(x))#define CLEAR(x) memset(x,0,sizeof(x))#define FILLL(x,c) memset(x,c,sizeof(x))using namespace std;const double eps = 1e-9;#define LL long long #define pb push_backconst int maxn  = 11000;double ax , ay, bx,by,cx,cy,dx,dy;double p ,q ,r;double s(double x1 ,double y1 ,double x2,double y2){     return sqrt((x2- x1)*(x2 -x1) + (y2 - y1)*(y2 -y1));}double f3(double a,double x,double y){ double x2  = cx + (dx- cx)*a;     double y2  = cy + (dy-cy)*a;     return s(x,y,x2,y2)/r +  s(x2,y2,dx,dy)/q;}double f2(double x ,double y){  double left = 0;  double right =1;  while(right - left>1e-6){   double  lmid = (left +right )/2;   double  rmid = (lmid + right)/2;    if(f3(lmid,x,y)>f3(rmid,x,y)){      left = lmid;    }else{     right = rmid;    }  //  cout << lmid << "  "<<rmid <<endl;  }     return f3(left,x,y);}double f(double a){ double x = ax + (bx-ax)*a; double y = ay + (by-ay)*a; double ans = s(ax,ay,x,y)/p; ans += f2(x,y); return ans;}void solve(){    double left = 0;    double right =1;    while(right - left > 1e-6){    double lmid = (left +right)/2;    double rmid = (lmid +right)/2;    if(f(lmid)>f(rmid)){            left = lmid;    }else{        right = rmid;    }        }    double ans = f(left);    printf("%.2f\n",ans);}int main(){    int  t;    cin >>t ;    while(~scanf("%lf%lf%lf%lf",&ax,&ay,&bx,&by),t--){      scanf("%lf%lf%lf%lf",&cx,&cy,&dx,&dy);      scanf("%lf%lf%lf",&p,&q,&r);      solve();    //  cout << f3(1,0,0)<<endl;    }    return 0;}


原创粉丝点击