给出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.