三分——BZOJ1857/Luogu2571 [SCOI2010]传送带

题面:BZOJ1857 Luogu2571
观察题目加上一定分析计算画图像等等可以得出,从某一条传送带的某一位置直接到达终点的函数是一个二次函数
这一结论同样可以推到两条传送带上
我们看作从第一条传送带的某一点直接到达第二条传送带的某一点(把这个点当终点好了),再沿着传送带到终点
这样我们就可以搞一搞喜闻乐见的三分啦OWO

这个其实是三分套三分啦,首先三分第一条传送带的点,然后把这个点当终点,三分第二条传送带的某一点,这样就满足一开始得出的结论了

如何计算路径长度和时间?
路径分三段,从起点沿传送带1到第一个点,第一个点直线到第二个点,第二个点沿传送带2到终点
首先我们三分的是每条传送带的指定点到起点(终点)的长度,所以第一段和最后一段无需计算
第二段嘛。。。我们首先计算出两个点相对于整条传送带位置的比例(举个例子某一点到起点的距离与整条的长比例是1:4)
这样我们就可以快速地算出每个点的具体坐标了
x坐标:该传送带起始点x坐标+比例*(该传送带终点x坐标-该传送带起点x坐标)
y坐标同理
然后直接勾股定理计算距离即可

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <ctime>
#include <map>
#include <queue>
#include <cstdlib>
#include <string>
#include <climits>
#include <set>
#include <vector>
using namespace std;
typedef double D;
D ax,ay,bx,by,cx,cy,dx,dy,a,b,c,L1,L2;
inline D sqr(D x){return x*x;}
inline D sanfen(D x){
    D wx=L1?ax+(bx-ax)*(x/L1):ax,wy=L1?ay+(by-ay)*(x/L1):ay;//第一条传送带x点的坐标
    D ans,l=0,r=L2;
    while(r-l>1e-9){
        D l1=l+(r-l)/3,l2=l1+(r-l)/3;
        D vx=L2?cx+(dx-cx)*(l1/L2):cx,vy=L2?cy+(dy-cy)*(l1/L2):cy;//第二条传送带l1点的坐标
        D k1=x/a+(L2-l1)/b+sqrt(sqr(vx-wx)+sqr(vy-wy))/c;//l1总时间
        vx=L2?cx+(dx-cx)*(l2/L2):cx,vy=L2?cy+(dy-cy)*(l2/L2):cy;//第二条传送带l2点的坐标
        D k2=x/a+(L2-l2)/b+sqrt(sqr(vx-wx)+sqr(vy-wy))/c;//l2总时间
        if(k1-k2<1e-9&&k2-k1<1e-9)l=l1,r=l2;
        else if(k2-k1>1e-9)r=l2;
        else l=l1;
    }
    D vx=L2?cx+(dx-cx)*(l/L2):cx,vy=L2?cy+(dy-cy)*(l/L2):cy;
    ans=x/a+(L2-l)/b+sqrt(sqr(vx-wx)+sqr(vy-wy))/c;
    return ans;
}
int main()
{
    scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy);
    scanf("%lf%lf%lf",&a,&b,&c);
    L1=sqrt(sqr(ax-bx)+sqr(ay-by));L2=sqrt(sqr(cx-dx)+sqr(cy-dy));
    D l=0,r=L1;
    while(r-l>1e-9){
        D l1=l+(r-l)/3,l2=l1+(r-l)/3;
        D k1=sanfen(l1),k2=sanfen(l2);
        if(k1-k2<1e-9&&k2-k1<1e-9)l=l1,r=l2;
        else if(k2-k1>1e-9)r=l2;
        else l=l1;
    }
    printf("%.2lf",sanfen(l));//计算答案
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值