Lintcode刷题-1861 · 老鼠跳跃-Go语言
1861 · 老鼠跳跃 困难
描述
有一个老鼠从高为n
的楼梯顶部跳跃下来,这个老鼠在偶数次跳跃时可以跳1, 3或者4个台阶,奇数次可以跳跃1, 2或者4个台阶。但是楼梯中间会有一些台阶上有胶水,如果跳到那些台阶上,老鼠就会被直接粘住,无法继续跳跃。你需要求出从这个楼梯顶部开始,老鼠有多少种方法能够到达地面,即第0层。若超过地面,也算是可以到达。例如从1跳跃到-1,和从1跳跃到0的方案不同。楼梯有无胶水的状态是从高往低输入的,即arr[0]
为楼梯的顶部。
其中,arr[i] == 0
代表当前老鼠所在的位置无胶水,arr[i] == 1
代表当前老鼠所在的位置有胶水。
2<=n<=50000
arr[i]=1代表台阶上有胶水,0代表没有
输入保证a[0] = a[n-1] = 0
答案需对1e9+7 取模
样例
样例1:
输入:
[0,0,0]
输出:
5
解释:
楼梯总共有3层。
第2层为起点,无胶水。
第1层,无胶水。
第0层,无胶水。
老鼠的跳法为:
2--odd(1)-->1--even(1)-->0
2--odd(1)-->1--even(3)-->-2
2--odd(1)-->1--even(4)-->-3
2--odd(2)-->0
2--odd(4)-->-2
样例2:
输入:
[0,0,1,0]
输出:
3
解释:
楼梯总共有4层。
第3层为起点,无胶水。
第2层,无胶水。
第1层,有胶水。
第0层,无胶水。
思路
算法 DP动态规划
DP方程
dp[i][0/1]
表示奇数次/偶数次跳到i位置的方案数
0代表even偶数
1代表odd奇数
由于题目的arr是从高到低给出的,那么arr[0]
就是我们的最高层
for i 0:n
这种枚举方式就是从高层到底层
DP边界条件
dp[0][0]=1
偶数次跳到了0位置,那么下次就是奇数次(也就是第一次)
DP转移
如果奇数次跳到了i,那么i再往下跳应该是偶数次
如果偶数次跳到了i,那么i再往下跳应该是奇数次
奇数次可以跳1,2,4 偶数次可以跳1,3,4
dp[i][0]
去更新dp[i+odd][1]
dp[i][1]
去更新dp[i+even][0]
伪代码中i只用枚举到n-2,不枚举到n-1的原因是 n-1已经是地面了 不能再往下跳
func ratJump(arr []int) int {
const MOD = 1e9 + 7
n := len(arr)
dp := make([][]int64, n+4)
for i := range dp {
dp[i] = make([]int64, 2)
}
dp[0][0] = 1
odd := []int{1, 2, 4}
even := []int{1, 3, 4}
for i := 0; i < n-1; i++ {
for j := 0; j < 3; j++ {
if i+odd[j] >= n || arr[i+odd[j]] == 0 {
dp[i+odd[j]][1] += dp[i][0]
dp[i+odd[j]][1] %= MOD
}
if i+even[j] >= n || arr[i+even[j]] == 0 {
dp[i+even[j]][0] += dp[i][1]
dp[i+even[j]][0] %= MOD
}
}
}
res := int64(0)
for i := n - 1; i < n+4; i++ {
res = (res + dp[i][0] + dp[i][1]) % MOD
}
return int(res)
}