序言
今天是刷LT的一天,好好干饭,好好努力,好好加油哦!
Leetcode题目–576:出界的路径数
给定一个 m × n 的网格和一个球。球的起始坐标为 (i,j) ,你可以将球移到相邻的单元格内,或者往上、下、左、右四个方向上移动使球穿过网格边界。但是,你最多可以移动 N 次。找出可以将球移出边界的路径数量。答案可能非常大,返回 结果 mod 109 + 7 的值。
例子如下:
输入: m = 2, n = 2, N = 2, i = 0, j = 0
输出: 6
方法一:动态规划
class Solution:
def findPaths(self, m, n, maxMove, startRow, startColumn):
#创建一个网格
dp = [[0] * n for _ in range(m)]
for k in range(maxMove):
cur = [[0] * n for _ in range(m)]
for m_ in range(m):
for n_ in range(n):
if m_ == 0:
#如果这个格子在第一行,则明显可以往上走出去,所以v1 = 1 。
v1 = 1
else: v1 = dp[m_- 1][n_]
#如果格子不在第一行,则得往上看一行
#---------------------
if m_ == M-1:
#如果格子在最后一行,则可以往下可以走出去,所以v2= 1
v2 = 1
else: v2 = dp[m_+1][n_]
#如果格子不在最后一行,则往下看一行
#---------------------
if n_ == 0:
#如果在第一列,则可以往左走出去
v3 = 1
else: v3 = dp[m_][n_-1]
#---------------------
if n_ == n -1:
#如果在最后一列,则可以往右走出去
v4 = 1
else: v4 = dp[m_][n_+1]
#---------------------
cur[m_][n_] = (v1+v2+v3+v4)%(10**9 + 7)
dp = cur
return dp[startRow][startColumn]
方法二:BFS广度优化搜索
def findPaths( m, n, maxMove, startRow, startColumn):
#创建网格,使之数值都是0
dp = [[0]*n for _ in range(m)]
#定义方向 direction
dire = ((1,0),(-1,0),(0,1),(0,-1))
for _ in range(maxMove):
cur = [[0]*n for _ in range(m)]
#cur表示 for k = 1,2,3,4,,,maxMove的每一个状态
for i in range(m):
for j in range(n):
for di,dj in dire:
ni = i + di
nj = j + dj
if ni >= m or ni < 0 or nj >= n or nj < 0:
cur[i][j] += 1
else:
cur[i][j] = (cur[i][j] + dp[ni][nj]) %(10**9 + 7)
dp = cur
return dp[startRow][startColumn]
LT62:不同的路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
例子如下
输入:m = 3, n = 7
输出:28
输入:m = 3, n = 3
输出:6
输入:m = 3, n = 2
输出:3
方法一:动态规划
从start point开始,到网格的第一行和第一列都是只有一条路
然后往下走,会发现某一格子的路径数是由 左边格子数 加上 上面格子数 非常重要的信息
因此,可以用动态规划来做,除去第一行和第一列,某一格子的路径数是 等于 左边格子数 + 上面格子数
def uniquePaths(m, n):
#创建网格
dp = [[1]*n for _ in range(m)]
for i in range(m):
for j in range(n):
if i == 0 or j == 0:
continue
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[m-1][n-1]
方法二:bfs 广度优先搜索
我们已经知道规律
除去第一行和第一列,某一格子的路径数是 等于 左边格子数 + 上面格子数
所以可以考虑用bfs来做,可以加快速度:
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dp = [[0]*n for _ in range(m)]
return self.bfs(m-1,n-1,dp)
def bfs(self,i,j,dp):
if i == 0 or j == 0:
return 1
if dp[i][j]:
#如果dp[i][j]是0或者false的话 不return
return dp[i][j]
left = self.bfs(i-1,j,dp)
right = self.bfs(i,j-1,dp)
dp[i][j] = left + right
return dp[i][j]
题目三:
题目688–马在棋盘上
已知一个 NxN 的国际象棋棋盘,棋盘的行号和列号都是从 0 开始。即最左上角的格子记为 (0, 0),最右下角的记为 (N-1, N-1)。
现有一个 “马”(也译作 “骑士”)位于 (r, c) ,并打算进行 K 次移动。 如下图所示,国际象棋的 “马” 每一步先沿水平或垂直方向移动 2 个格子,然后向与之相垂直的方向再移动 1 个格子,共有 8 个可选的位置
现在 “马” 每一步都从可选的位置(包括棋盘外部的)中独立随机地选择一个进行移动,直到移动了 K 次或跳到了棋盘外面。求移动结束后,“马” 仍留在棋盘上的概率
例子如下
输入: 3, 2, 0, 0
输出: 0.0625
解释:
输入的数据依次为 N, K, r, c
第 1 步时,有且只有 2 种走法令 “马” 可以留在棋盘上(跳到(1,2)或(2,1))。对于以上的两种情况,各自在第2步均有且只有2种走法令 “马” 仍然留在棋盘上。
所以 “马” 在结束后仍在棋盘上的概率为 0.0625。
这道题跟之前足球出界的问题很像,不过足球是想要出界,这里是求 不会出界的可能性。
所以解题思路跟足球出界的差不多,也是把每一次的状态记录下来,然后再叠加
最后来一个sum up所有的可能性
代码如下:
class Solution:
def knightProbability(self, n: int, k: int, row: int, column: int) -> float:
dp = [[0]*n for _ in range(n)]
dire = ((1,2),(2,1),(2,-1),(1,-2),(-1,2),(-2,1),(-2,-1),(-1,-2))
dp[row][column] = 1
for _ in range(k):
cur = [[0]*n for _ in range(n)]
#记录每一次的状态
for i in range(n):
for j in range(n):
for di,dj in dire:
ni = i + di
nj = j + dj
if ni>=n or ni < 0 or nj >= n or nj < 0:
continue
else:
cur[ni][nj] += dp[i][j]
dp = cur
return sum(map(sum, dp)) / float(8 ** k)