hdu 3400 Line belt

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

从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_back
const 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值