8.8 迷之阶梯 2530

来源:互联网 发布:网络菜市场 编辑:程序博客网 时间:2024/06/04 18:44

  • 题目
  • 题解
  • 代码

题目

登上阶梯必须要按照它要求的方法,否则就无法登上阶梯。它要求的方法有以下三个限制:
1. 如果下一步阶梯的高度只比当前阶梯高1,则可以直接登上。
2. 除了第一步阶梯外,都可以从当前阶梯退到前一步阶梯。
3. 当你连续退下k后,你可以一次跳上不超过当前阶梯高度2^k的阶梯。比如说你现在位于第j步阶梯,并且是从第j + k步阶梯退下来的。那么你可以跳到高度不超过当前阶梯高度 + 2^k的任何一步阶梯。跳跃这一次只算一次移动。
开始时你在第1步阶梯。由于时间紧迫,我们需要你预先计算出登上迷之阶梯的最少移动次数。

题解

可以用动态规划
有两种情况:
1.这一步阶梯只比上一步阶梯高1,f[i]=f[i-1]+1
2.从第j(1<=j<=i-1)级阶梯退后k(1<=k<=j-1)级阶梯然后跳上这一步阶梯,f[i]=f[j]+1+(j-k)

O(n3)

也可以用搜索+记忆化,注意剪枝

代码

var  w:array[1..200]of longint;  m:array[0..200]of int64;  n,i,j,k:longint;  f:array[0..200]of longint;begin  assign(input,'ladder.in');  assign(output,'ladder.out');  reset(input);rewrite(output);  readln(n);  fillchar(f,sizeof(f),$7f);  f[1]:=0;  for i:=1 to n do    read(w[i]);  m[0]:=1;  for i:=1 to 31 do    m[i]:=m[i-1]*2;  for i:=32 to n do    m[i]:=m[i-1];  for i:=2 to n do    begin      if (w[i]-w[i-1]=1)and(f[i-1]+1<f[i]) then f[i]:=f[i-1]+1;      for j:=1 to i-1 do        for k:=1 to j-1 do          if (w[i]-w[k]<=m[j-k])and(f[j]+1+j-k<f[i]) then f[i]:=f[j]+1+j-k;    end;  if f[n]<>f[0] then writeln(f[n]) else writeln('-1');  close(input);close(output);end.
原创粉丝点击