8.8 两人过桥bridge 2529

  • 题目
  • 题解
  • 代码

题目

有n个人希望在晚上通过一座桥。在任何时刻,最多只能有两个人在桥上,并且必须要带着手电筒才能通过桥。现在的麻烦是只有一个手电筒,所以必须安排某种顺序,使得手电筒可以被带回去让更多的人过桥(手电筒必须由人带回,不可以从对岸扔过去)。 每个人都有不同的过桥时间,两个人一起过桥所用的时间等于其中较慢的一个。你的任务是要找出能在最短时间内使所有人都过桥的方案。

40%的数据满足:n<=100;
100%的数据满足:n<=1000

  样例读入       样例输出
     4            17
     1 
     2 
     5  
    10

可以先让1和2过桥,然后1回来,让5和10过桥,然后2再回来带1一起过桥,时间为:2+1+10+2+2=17。

题解

贪心,先排序
有两种策略,每次取效率最高的:
1.让最快的人来回带
2.先让最快和次快的人过去,然后最快回来,最慢和次慢过去,次快单独回来,带最快过去

从小到大做和从大到小做都可以,从小到大要保持手电筒、最快和次快在右边,从大到小则保持手电筒、最快和次快在左边
时间复杂度O(n)

          |     |
   左边   |      |   右边
 (起点)  |     |  (终点)
          |     |

代码

从大到小

var
  n,i,ans:longint;
  a:array[1..1000]of longint;

procedure qsort(l,r:longint);
var
  i,j,key,t:longint;
begin
  if l>=r then exit;
  i:=l;j:=r;
  key:=a[(l+r) div 2];
  repeat
    while a[i]do inc(i);
    while a[j]>key do dec(j);
    if i<=j then
      begin
        t:=a[i];a[i]:=a[j];a[j]:=t;
        inc(i);dec(j);
      end;
  until i>j;
  qsort(i,r);
  qsort(l,j);
end;

function min(a,b:longint):longint;
begin
  if athen exit(a) else exit(b);
end;

begin
  readln(n);
  for i:=1 to n do
    readln(a[i]);
  qsort(1,n);
  while n>3 do
    begin        
      ans:=ans+min(a[1]*2+a[n]+a[n-1],a[n]+a[2]*2+a[1]);
      n:=n-2;
    end;
  if n=3 then ans:=ans+a[1]+a[2]+a[3]
         else ans:=ans+a[n];
  writeln(ans);
end.

从小到大

var
  n,i:longint;
  a,f:array[1..1000]of longint;

procedure qsort(l,r:longint);
var
  i,j,key,t:longint;
begin
  if l>=r then exit;
  i:=l;j:=r;
  key:=a[(l+r) div 2];
  repeat
    while a[i]do inc(i);
    while a[j]>key do dec(j);
    if i<=j then
      begin
        t:=a[i];a[i]:=a[j];a[j]:=t;
        inc(i);dec(j);
      end;
  until i>j;
  qsort(i,r);
  qsort(l,j);
end;

function min(a,b:longint):longint;
begin
  if athen exit(a) else exit(b);
end;

begin
  readln(n);
  for i:=1 to n do
    readln(a[i]);
  qsort(1,n);
  f[1]:=a[1];f[2]:=a[2];
  for i:=3 to n do
    f[i]:=min(f[i-1]+a[i]+a[1],f[i-2]+a[i]+a[1]+a[2]*2);
  writeln(f[n]);
end.


你可能感兴趣的:(贪心,动态规划)