HDU 3400 Line belt (三分)

原题链接: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段公式:time = |EF|/R + |FD|/Q

所以当F在E,D之间且R!= Q时,函数递减,当F在ED外时,函数递增

对于凸性函数,我们可以用三分解决

 

 

所以我们将EF段和FD段用三分求出最优解,再返回到E点的坐标

将AB三分,比较E_1E_2的大小,再进行三分,实现一个三分套三分,就能解题了

代码如下

#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;
}

 

转载于:https://www.cnblogs.com/bestsort/p/10588866.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值