bzoj1857 SCOI2010传送带

32 篇文章 0 订阅
2 篇文章 0 订阅

Description

在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在lxhgww想从A点走到D点,他想知道最少需要走多长时间
Input

输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By 第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy 第三行是3个整数,分别是P,Q,R
Output

输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位
Sample Input

0 0 0 100

100 0 100 100

2 2 1

Sample Output

136.60

HINT

对于100%的数据,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10

题意是很好理解的,你会发现所有的路径总会经过三个速度不同的地方,也就是说AB,CD和其他地方是必定会经过的,所以我们就可以对AB先进行三分,为什么不是二分?因为我们发现没有让我们二分的判断条件,而在三分的时候,你只要手玩半个小时就会发现规律:
    我们设每次三分出的两个点为ij。
    如果solve(i)<solve(j)则答案区间必定在ij之间否则l:=i;
    然后同样的再对CD套一个三分就可以了。
type node=record
    x,y:real;
end;
var
        i,j,n:longint;
    a:array[0..4]of node;
    v1,v2:node;
    p,q,m:real;
function dis(x1,y1,x2,y2:real):real;
begin
    exit(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
end;
function get_dis(l1,l2:real):real;
var
    x1,x2,y1,y2:real;
begin
        x1:=A[0].x+v1.x*l1;
    y1:=A[0].y+v1.y*l1;
        x2:=A[3].x+v2.x*l2;
    y2:=A[3].y+v2.y*l2;
        //writeln(x1:0:2,' ',y1:0:2,' ',x2:0:2,' ',y2:0:2,' ',r:0:2);
        exit(dis(a[0].x,a[0].y,x1,y1)/p+dis(x1,y1,x2,y2)/m+dis(x2,y2,A[3].x,A[3].y)/Q);
end;
function solve(l1:real):real;
var
    l,r,mid1,mid2,k1,k2:real;
    i:longint;
begin
        l:=0;
    r:=1;
    for i:=1 to 200 do
        begin
                mid1:=(l+r)/2;
        mid2:=(mid1+r)/2;
                k1:=get_dis(l1,mid1);
                k2:=get_dis(l1,mid2);
                if(k1<k2)then r:=mid2 else l:=mid1;
        end;
        exit(get_dis(l1,l));
end;
procedure main;
var
    i:longint;
    l,r,mid1,mid2,k1,k2:real;
begin
    for i:=0 to 3 do read(a[i].x,a[i].y);
        readln(p,q,m);
        v1.x:=A[1].x-A[0].x;
    v1.y:=A[1].y-A[0].y;
         v2.x:=A[2].x-A[3].x;
    v2.y:=A[2].y-A[3].y;
        l:=0;
    r:=1;
    for i:=1 to 200 do
    begin
                mid1:=(l+r)/2;
        mid2:=(mid1+r)/2;
                k1:=solve(mid1);
                k2:=solve(mid2);
                if(k1<k2)then r:=mid2 else l:=mid1;
        end;
        writeln(solve(l):0:2);
end;
begin
    main;
end.

这可以算是三分套三分的模板吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值