【水】uva10037 过桥

给出n个人所需过桥的时间,每次最多两人过桥,过桥时间为最长的人的时间。求最快所有人全部过桥方案。

贪心。先从小到大排,易知

n=1 时 ans=a[1]

n=2,ans=max(a[1],a[2])

n=3,ans=a[1]+a[2]+a[3]

初始化F[1、2、3],记F[n](n>=4)为前n个人过河且1、2个人在河左岸时所用的最短时间。要弄两个人过去易得两种方案:

  • 1到右岸去,带i-1回来,1再到右岸,带i回来,用时是2*a[1]+a[i-1]+a[i]
  • 1到右岸去,i-1、i一起回来,2到右岸,带1回来(适用于a[i-1]、a[i]较大且相差较小时),用时a[1]+2*a[2]+a[i]

故F[n]=Min{2*a[1]+a[i-1]+a[i],a[1]+2*a[2]+a[i]}+F[n-2]

转移时记下是第几种方案。若n为奇数从3一步步向后推,若n为偶数从2开始推。

#   Problem Verdict Language Run Time Submission Date
11591812 10037 Bridge Accepted PASCAL 0.016 2013-04-11 13:49:55
program p10037;

Const
  sol1=true;
  sol2=false;

Var
 a,f:array[0..1002] of longint;
 g:array[0..1002] of boolean;
 t,n,i,o:longint;

Procedure fopen;
  begin
  assign(input,'p10037.in');
  assign(output,'p10037.out');
  reset(input);
  rewrite(output);
end;

Procedure fclose;
  begin
  close(input);
  close(output);
end;

Function max(a,b:longint):longint;inline;
  begin
  if a>b then exit(a);exit(b);
end;

Procedure qsort(l,r:longint);
Var
 i,j,x,y:longint;
  begin
  i:=l;j:=r;x:=a[l+round(0.618*(r-l))];
    repeat
    while a[i]<x do inc(i);
    while a[j]>x do dec(j);
    if i<=j then 
      begin
      y:=a[i];
      a[i]:=a[j];
      a[j]:=y;
      inc(i);
      dec(j);
    end;
  until i>j;
  if i<r then qsort(i,r);
  if l<j then qsort(l,j);
end;

Procedure BasicPrint(P:longint;flag:boolean);inline;
  begin
  case p of 
    1:
    begin
    if flag then writeln(a[1]);
    writeln(a[1]);
    //writeln;
  end;
    2:
    begin
    if flag then writeln(max(a[1],a[2]));
    writeln(a[1],' ',a[2]);
   //writeln;
  end;
    3:begin
    if flag then writeln(a[1]+a[2]+a[3]);
    writeln(a[1],' ',a[3]);
    writeln(a[1]);
    writeln(a[1],' ',a[2]);
    //writeln;
  end;
  end;
end;

Procedure StepPrint(P:longint;kind:boolean);inline;
  begin
  if kind=sol1 then
    begin
    writeln(a[1]);
    writeln(a[1],' ',a[p-1]);
    writeln(a[1]);
    writeln(a[1],' ',a[p]);
    exit;
  end;
  writeln(a[1]);
  writeln(a[p-1],' ',a[p]);
  writeln(a[2]);
  writeln(a[1],' ',a[2]);
end;

  begin

  readln(t);
  while t>0 do begin dec(t);
  readln;
  readln(n);
  for i:=1 to n do 
    readln(a[i]);
  qsort(1,n);
  if n<=3 then basicprint(n,true) else
    begin
    f[1]:=a[1];
    f[2]:=max(a[1],a[2]);
    f[3]:=a[1]+a[2]+a[3];
    for i:=4 to n do
      if 2*a[1]+a[i-1]+a[i]<=a[1]+2*a[2]+a[i] then
        begin
        g[i]:=Sol1;
        f[i]:=2*a[1]+a[i-1]+a[i]+f[i-2]
      end else
        begin
        g[i]:=Sol2;
        f[i]:=a[1]+2*a[2]+a[i]+f[i-2];
      end;
    
    if odd(n) then o:=3 else o:=2;
    writeln(f[n]);
    basicprint(o,false);
    inc(o,2);
    while o<=n do
      begin
      Stepprint(o,g[o]);
      inc(o,2);
    end;
  end;
  if t>0 then writeln;
      
  end;//while t

end.
原文地址:https://www.cnblogs.com/htfy/p/3015487.html