[编程题]:走台阶
题目描述
小明回家要走一个阶梯,一共有n步。小明走阶梯有两个特点:
- 每次只能走1步或者2步;
- 不能连着两次走2步;
请计算他一共有多少种走法。
输入描述
楼梯的层数N,其中0 <= N < 100
输出描述
总共有多少种走法,以整数输出。
示例1
输入
2
输出
2
说明:2级台阶共有2种走法
示例2
输入
4
输出
4
说明:4级台阶共有4种走法
解题思路
很容易想到 斐波那契数列, 但是这里有一个“不能连着两次走2步”的限制条件。不能采用那种泰简单的动态规划思路。
如果用DFS搜索也可以,但是时间复杂度太高,肯定过不了的。
但是换一种思路,不要局限于常见的动态规划方法。
常见的动态规划是:设一个dp数组,再加上状态转移方程、边界条件就可以了。
本题中,“每次可以走1步或则2步,不能连着走2步”。因此,状态 i 不仅跟状态 i - 1 和状态 i - 2 有关,还跟到达状态 i - 1 和 状态 i - 2 的最后一步有关。如果到达状态 i - 2 的最后一步走了2步,那么就不能由状态 i - 2 转移到状态 i 了;如果最后一步走了1步,那么可以从状态 i - 2 转移到状态 i 。
因此。从分析可以看出:应该有两个状态转移。最后一步走了1步对应有一个状态转移;最后一步走了2步有另外一个状态转移。
状态转移
既然如此,为什么不可以设两个状态转移数组 dp[i][2].
dp[i][0]表示到达第 i 级台阶,并且最后一步走了 1 步的走法数;
dp[i][1]表示到达第 i 级台阶,并且最后一步走了 2 步的走法数。
有了这两个状态转移数组,就可以根部最后一步的不同情况进行不同的转移以满足题目中提出的要求。
状态转移方程
边界条件
dp[1][0] = 1 到达台阶 1 ,且最后一步走了1步的共有1种走法;
dp[1][1] = 0 到达台阶 1 ,且最后一步走了2步的共有0种走法;
dp[2][0] = 1 到达台阶 2 ,且最后一步走了1步的共有1种走法;
dp[2][1] = 1 到达台阶 2 ,且最后一步走了2步的共有1种走法;
状态转移方程
dp[i][0] = dp[i - 1][0] + dp[i - 1][1] (从i - 1级台阶到达 i 级台阶,走1步,到达i - 1级台阶的最后一步可1步也可2步)
dp[i][1] = dp[i - 2][0] (从i - 2级台阶到达 i 级台阶,走2步,因此到达i - 2级台阶的最后一步只能走1步)
代码
JAVA
import java.util.Scanner;
public class Main {
private static int res = 0;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
if (n <= 2) {
System.out.println(n);
return;
}
long[][] dp = new long[n + 1][2];
dp[1][0] = 1;
dp[1][1] = 0;
dp[2][0