原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3400
题意:给定两条线段AB,CD,在这两条线段上速度分别为P,Q,在其他地方速度为R,让求A 到 D点的最短时间
思路:我们可以知道 一定从AB线段中某一点离开(可能直接从A离开,也可能从AB段中的某一点离开),然后进入到CD中点某一点,设从AB线段的E点离开,进入到CD线段的F点。
我们假设E点已确定,现在就只需要找出F点即可,由EF段和FD段公式:
所以当F在E,D之间且R!= Q时,函数递减,当F在ED外时,函数递增
对于凸性函数,我们可以用三分解决
所以我们将EF段和FD段用三分求出最优解,再返回到E点的坐标
将AB三分,比较和的大小,再进行三分,实现一个三分套三分,就能解题了
代码如下
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define For(a,b) for(int a=0;a<b;a++)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn = 55;
const int INF = 0x3f3f3f3f;
const int inf = 0x3f;
const double EPS = 1e-7;
struct node{
double x,y;
node(){}; //构造函数
node(double a,double b){x = a,y = b;} //构造函数
};
node A,B,C,D;
double P,Q,R;
double dis(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));} //两点间距离
double time(node a,node b){return dis(a,b)/P;}
double time(node a,node b,node c){return dis(a,c)/Q+dis(a,b)/R;}
double third2(node l,node r,node buf1){ //三分求出EF和DF的最佳耗时,其中buf1即为F点
node m = node((l.x+r.x)/2,(l.y+r.y)/2);
node mm = node((m.x+r.x)/2,(m.y+r.y)/2);
double a,b;
a = time(m,buf1,D);
b = time(mm,buf1,D);
if(abs(a-b)<=EPS)
return a;
return a<b?third2(l,mm,buf1):third2(m,r,buf1);
}
double third1(node l,node r){
node m = node((l.x+r.x)/2,(l.y+r.y)/2);
node mm = node((m.x+r.x)/2,(m.y+r.y)/2);
double ansm,ansmm;
ansm = third2(C,D,m);
ansmm = third2(C,D,mm);
if(abs(ansm-ansmm) <= EPS)
return ansm+time(A,mm);
return ansm+time(A,m)<ansmm+time(A,mm)?third1(l,mm):third1(m,r);//根据总耗时大小选择要舍弃的段
}
int main()
{
int t;
cin >> t;
while(t--){
cin >> A.x>>A.y>>B.x>>B.y>>C.x>>C.y>>D.x>>D.y;
cin >> P>>Q>>R;
printf("%.2lf\n",third1(A,B));
//cout <<third1(A,B) <<endl;
}
return 0;
}