1. 程式人生 > >LeetCode-【動態規劃】-“馬”在棋盤上的概率

LeetCode-【動態規劃】-“馬”在棋盤上的概率

已知一個 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。

注意:

  • N 的取值範圍為 [1, 25]
  • K 的取值範圍為 [0, 100]
  • 開始時,“馬”總是位於棋盤上
class Solution {
    public double knightProbability(int N, int K, int r, int c) {
        double[][] dp=new double[N][N];
        for(double[] d:dp){
            Arrays.fill(d,1);
        }
        int[][] dt={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2}};
        for(int k=1;k<=K;k++){
            double[][] t=new double[N][N];
            for(int i=0;i<N;i++){
                for(int j=0;j<N;j++){
                    for(int[] d:dt){
                        int x=i+d[0];
                        int y=j+d[1];
                        if(x<0||x>=N||y<0||y>=N)
                            continue;
                        t[i][j]+=dp[x][y];
                    }
                }
            }
            dp=t;
        }
        return dp[r][c]/Math.pow(8,K);
    }
}