题目:
在一个大晴天,Oliver与同学们一共N人出游,他们走到一条河的东岸边,想要过河到西岸。而东岸有一条小船。 船太小了,一次只能乘坐两人。每个人都有一个渡河时间T,船划到对岸的时间等于船上渡河时间较长的人所用时间。 现在已知N个人的渡河时间T,Oliver想要你告诉他,他们最少要花费多少时间,才能使所有人都过河。 注意,只有船在东岸(西岸)时东岸(西岸)的人才能坐上船划到对岸。
分析:
这题就十分类似此前的几个小盆友拿着手电筒过独木桥的题目。经过不断的推导,最优方法只能在两种方法之中诞生,一种是最快的那个人带一个最慢的也就是Time[I](因为先前快排过所以越后面就是越慢的老头),最快的那个人再把船送回来;另一种是t[1]和t[2]一起先过去,记录了t[2]的时间一次,然后T[1]回来,记录了T[1]的时间,再让两个最慢的老头过去,也就是T[I]和T[I-1],再让T[2]把船送回来。综合起来,得到状态转移方程:f[i]:=min(f[i-1]+time[1]+time[i],f[i-2]+time[1]+time[i]+time[2]*2);初始化是f[1]=a[1],f[2]=a[2];
附上代码:
const maxn=100000; var time,f:array [0..maxn] of longint; n:longint; procedure init; var i:longint; begin readln(n); for i:=1 to n do readln(time[i]); end; procedure qsort(l,r:longint); var i,j,k,mid:longint; begin i:=l; j:=r; mid:=time[(l+r) shr 1]; repeat while time[i]<mid do inc(i); while time[j]>mid do dec(j); if i<=j then begin k:=time[i]; time[i]:=time[j]; time[j]:=k; inc(i); dec(j); end; until i>j; if l<j then qsort(l,j); if i<r then qsort(i,r); end; function min(a,b:longint):longint; begin if a<b then exit(a); exit(b); end; procedure main; var i,j:longint; begin qsort(1,n); f[1]:=time[1];f[2]:=time[2]; for i:=3 to n do f[i]:=min(f[i-1]+time[1]+time[i],f[i-2]+time[1]+time[i]+time[2]*2); write(f[n]); end; begin init; main; end.
