W3 school 菜鸟教程 我要自学网 信息学奥赛NOI 花哥的博客 不逼自己一把,怎知自己有多优秀——校长语录

1439:【SCOI2010】传送带

1439:【SCOI2010】传送带(一本通网站原题链接)

【分析】

  这个题目其实我想的比较简单,问题的决策点在于何时离开第一个传送带,何时上第二个传送带。两个决策点可变为一个决策问题用两次。我们把这个问题换一个说法。你在笔直的河岸边发现河中一人求救,己知你水中速度和岸上速度,求你到达求救者的最短时间。那这个决策就是你在何处下水。这问题用一个极限思考:河岸看作足够长,在河岸的两端入水,到达时间都是很大,当向中点某点靠近时,这个时间在缩小。换言之,把河岸看作一个坐标轴,入水点与你所在位置的差为自变量x,那函数值时间t是x的一个函数,这个函数的单调性为先减后增型(实质是一个单峰函数),那解决它的办法就是三分法。回到本题,我们的策略可以这样描述:先把第一个传送带三分,分点分别为A、B。选择A还是B那将取决于从哪里下传送带更快。这个快与慢还需要第二次决策:从哪里上第二个传送带。我们可以先用三分法算出从A下传送带的最快时间,同样三分法算出从B下传送带的最快时间,那我们就知道A、B两点我们选择哪一点了。接着就是把A、B的距离无限靠近就好。注意,本题有一个特殊情形,我们的思路是两个三分法嵌套,外层最好用do循环,否则外层中传送带长度为0直接就不进入循环了

【AC代码】

  (说明:为了熟悉下结构体重载,我选择了用结构体,具体实现方法因你而改变)

//1439:【SCOI2010】传送带 
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
struct point{
    double x,y;
    void operator = (const point p) {
        //point t;
    x=p.x;
    y=p.y;
    //return t;
    }
    point operator * (const int n) {
        point t;
    t.x=x*n,t.y=y*n;
    return t;
    }
    point operator / (const int n) {
        point t;
    t.x=x/n,t.y=y/n;
    return t;
    }
    point operator +(const point  p)
    {
        point t;
        t.x=x+p.x,t.y=y+p.y;
    return t;
    }
}a[4],b[4],md[4];
double q,p,r;
double dis(point w,point e)
{
    double h,v,s;
    h=w.x-e.x;
    v=w.y-e.y;
    s=sqrt(h*h+v*v);
    //cout<<w.x<<' '<<w.y<<' '<<e.x<<' '<<e.y<<' '<<s<<endl;
    return s;
}
double jl(int m,int n)
{
    double s=0;
    s+=dis(a[0],md[m])/p;
    s+=dis(md[m],md[n])/r;
    s+=dis(md[n],a[3])/q;
    return s;
}
void pr(point w)
{
    cout<<w.x<<' '<<w.y<<endl;
}
int main(){
    for(int i=0;i<4;i++)cin>>a[i].x>>a[i].y;
    cin>>p>>q>>r;
    b[0]=a[0],b[1]=a[1];
    do
    {
        md[0]=(b[0]*2+b[1])/3;
        md[1]=(b[0]+b[1]*2)/3;
        b[2]=a[2],b[3]=a[3];
        while(dis(b[2],b[3])>1e-11)
        {
            md[2]=(b[2]*2+b[3])/3;
            md[3]=(b[2]+b[3]*2)/3;
            if(jl(0,2)<jl(0,3))b[3]=md[3];
            else b[2]=md[2];
        }
        if(jl(0,3)<jl(1,3))b[1]=md[1];
        else b[0]=md[0];
    }while(dis(b[0],b[1])>1e-11);
    cout<<fixed<<setprecision(2)<<jl(0,2);
    return 0;
}

 

posted @ 2020-04-05 23:17  耍人  阅读(471)  评论(0编辑  收藏  举报