688.骑士在棋盘上的概率

127 阅读1分钟

题目:
在一个 n x n 的国际象棋棋盘上,一个骑士从单元格 (row, column) 开始,并尝试进行 k 次移动。行和列是 从 0 开始 的,所以左上单元格是 (0,0) ,右下单元格是 (n - 1, n - 1) 。

象棋骑士有8种可能的走法,如下图所示。每次移动在基本方向上是两个单元格,然后在正交方向上是一个单元格。
算法:
方法一: 走了k步之后,结果=在棋盘内的路径次数/(出界的路径次数+在界内的路径次数) 因为dp[step]依赖于dp[step - 1],所以从dp[0]开始计算,所有的dp[step - 1]都已经计算好了。棋盘,二维空间,三维dp类的步数问题都类似。
这里用到的技巧是dp直接存储概率,而不是计算出界,在界内的次数,然后计算概率(就像上面划掉的思路,不好实现,考虑直接计算概率)。
每个位置有八个选择,几次出界,几次在界内容易得到,直接计算概率。

110.3
0.4dp[step][i][j]0.2
0.100

dp[step][i][j] 等于所有八个选择的概率之和/8

func knightProbability(n int, k int, row int, column int) float64 {
	dicts := [][]int{[]int{-2,1},[]int{-2,-1},[]int{-1,2},[]int{-1,-2},[]int{2,1},[]int{2,-1},[]int{1,2},[]int{1,-2}}
	dp := make([][][]float64, k + 1)
	for step := range dp {
		dp[step] = make([][]float64, n)
		for i := range dp[step] {
			dp[step][i] = make([]float64, n)
			for j := range dp[step][i] {
				if step == 0 {
					dp[step][i][j] = 1
				} else {
					cnt := float64(0)
					for _, dict := range dicts {
						i1 := i + dict[0]
						j1 := j + dict[1]
						if 0 <= i1 && i1 < n && 0 <= j1 && j1 < n {
							cnt = cnt + dp[step - 1][i1][j1]
						}
					}
					dp[step][i][j] = cnt / 8
				}
			}
		}
	}
	return dp[k][row][column]
}