zoukankan      html  css  js  c++  java
  • 两人过桥

    两人过桥(bridge.???)

    问题描述:
    有 n 个人希望在晚上通过一座桥。在任何时刻,最多只能有两个人在桥上,并且必须
    要带着手电筒才能通过桥。现在的麻烦是只有一个手电筒,所以必须安排某种顺序,使得手
    电筒可以被带回去让更多的人过桥(手电筒必须由人带回,不可以从对岸扔过去)。
    每个人都有不同的过桥时间,两个人一起过桥所用的时间等于其中较慢的一个。你的
    任务是要找出能在最短时间内使所有人都过桥的方案。
    输入格式:
    第一行是一个整数 n。
    接下来有 n 行,每一行给出一个人的过桥时间(整数,单位:秒)。
    每个人的过桥时间不超过 100 秒。
    输出格式:
    输出一行一个数,表示所有人过桥的最短时间。
    样例输入:
    4
    1
    2
    5
    10

    样例输出:
    17
    样例解释:
    可以先让 1 和 2 过桥,然后 1 回来,让 5 和 10 过桥,然后 2 再回来带 1 一起过桥,时
    间为:2+1+10+2+2=17。
    数据限制:
    40%的数据满足:n<=100;
    100%的数据满足:n<=1000。

    分析
    贪心法

    最简单的一个贪心策略是:让一个最快的人来回带人
    但是显然是错误的比如4个人:1 1 100000 100000
    最快的来回带的话要:1+1+100000+1+100000=200003
    但是如果先将1 1运过去的话,然后1回来,再让100000 100000一起过去
    再让右边的1来回一趟,就只要1+1+100000+1+1=100004,这样显然小了

    所以第一种贪心的策略显然是不合理的,下面换种贪心策略:
    首先,慢的肯定是过了桥之后不回来了
    就上面那种情况,我们就是先将最快的两个带过去,
    然后快的一个过来,让两个慢的过去,然后让快的再回来,……
    但是这种贪心策略也不优,因为:
    如果是1 10000 10000 10000,答案又不对了(还是第一种策略优)

    结合以上两点,对于最慢的两个人我们有两种处理方法就是:
    1、让最快的人来回带
    2、让最快的两个人过去,再让最慢的两个一起过去,这样就减少了最慢的重复计算

    关于这个贪心策略的证明是:
    首先,过桥速度排在第三名之后的人不可能担任送回手电筒的任务,原因是不如速度第一和第二的人送回来得高效。这样,
    当前左岸速度最慢的人过桥后就不可能再回来,那么我们可以优先让速度慢的过河,因为其不可能返回,先过后过等效。如此一来,就可以得到上述的贪心策略。

    程序:

    var
    a:array[0..12000] of longint;
    n,i:longint;
    ans,x,y:int64;
    
    procedure kp(l,r:longint);
    var
    i,j,mid:longint;
    begin
        if l>=r then exit;
        i:=l;j:=r;mid:=a[(i+j) div 2];
        repeat
             while a[i]<mid do inc(i);
             while a[j]>mid do dec(j);
             if i<=j then
             begin
                 a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
                 inc(i);dec(j);
             end;
        until i>j;
        kp(l,j);
        kp(i,r);
    end;
    
    begin
        assign(input,'bridge.in');
        assign(output,'bridge.out');
        reset(input);
        rewrite(output);
        readln(n);
        for i:=1 to n do
        read(a[i]);
        kp(1,n);
        ans:=0;
        i:=n;
        while true do
        begin
            if i=2 then ans:=ans+a[2];
            if i=3 then ans:=ans+a[1]+a[2]+a[3];
            if i<=3 then break;
            x:=2*a[2]+a[1]+a[i];
            y:=2*a[1]+a[i]+a[i-1];
            if x<y then ans:=ans+x else ans:=ans+y;
            i:=i-2;
        end;
        write(ans);
        close(input);
        close(output);
    end.
    
    
    
    
  • 相关阅读:
    ClickHouse之访问权限控制
    ClickHouse之集群搭建以及数据复制
    ClickHouse之简单性能测试
    ClickHouse之初步认识
    从完整备份恢复单个innodb表
    MHA快速搭建
    MySQL 5.7最新版本的2个bug
    Greenplum各种Tips(不定时更新)
    MySQL 5.7贴心参数之binlog_row_image
    TCP窗口机制与流量控制
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/9500070.html
Copyright © 2011-2022 走看看