回 帖 发 新 帖 刷新版面

主题:帮我解题!《过河》

第十一届全国青少年奥林匹克信息学联赛复赛提高组试题

过河
(river.pas/c/cpp)

【问题描述】

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。
题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

【输入文件】

输入文件river.in的第一行有一个正整数L(1 <= L <= 109),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1 <= S <= T <= 10,1 <= M <= 100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

【输出文件】

输出文件river.out只包括一个整数,表示青蛙过河最少需要踩到的石子数。

【样例输入】

10
2 3 5
2 3 5 6 7

【样例输出】

2

【数据规模】

对于30%的数据,L <= 10000;
对于全部的数据,L <= 1 E+9。

回复列表 (共1个回复)

沙发

program river;
const maxm=100;
var x,p:array [0..maxm] of longint;
    b:array [-10..90] of boolean;
    c:array [0..maxm,0..9] of longint;
    L,s,t,m,n,i,j,v,k,best,min:longint;
  function can(len:longint):boolean;
  begin
    if len<0
    then can:=false
    else if len>=s*s-s
         then can:=true
         else can:=b[len]
  end;
begin
  assign(input,'river.in');
  reset(input);
  readln(L);
  readln(s,t,m);
  for i:=1 to m do read(x[i]);
  n:=0;
  for i:=1 to m do
    if x[i]<L
    then begin
           inc(n);
           p[n]:=x[i]
         end;
  readln;
  close(input);
  if s=t
  then begin
         best:=0;
         for i:=1 to m do
           if p[i] mod s=0
           then inc(best);
         assign(output,'river.out');
         rewrite(output);
         writeln(best);
         close(output);
         halt
       end;
  fillchar(b,sizeof(b),false);
  b[0]:=true;{-10..90}
  for i:=1 to s*s-s-1 do
    for j:=s to t do
      b[i]:=b[i] or b[i-j];
  for i:=1 to n-1 do
    for j:=1 to n-1 do
      if p[j]>p[j+1]
      then begin
             v:=p[j];
             p[j]:=p[j+1];
             p[j+1]:=v
           end;
  p[0]:=0;
  for i:=0 to n do
    for j:=0 to t-1 do
      c[i,j]:=n+1;
  c[0,0]:=0;
  for i:=1 to n do
    for j:=0 to t-1 do
      if p[i]-j<=p[i-1]
      then c[i,j]:=c[i-1,j-p[i]+p[i-1]]
      else begin
             min:=n+1;
             for k:=0 to t-1 do
               if can(p[i]-j-p[i-1]+k) and (c[i-1,k]<min)
               then min:=c[i-1,k];
             if j=0 then c[i,j]:=min+1 else c[i,j]:=min
           end;
  best:=n+1;
  for i:=0 to t-1 do
    if c[n,i]<best
    then best:=c[n,i];
  assign(output,'river.out');
  rewrite(output);
  writeln(best);
  close(output)
end.

我来回复

您尚未登录,请登录后再回复。点此登录或注册