LeetCode——688. Knight Probability in Chessboard

一.題目連接:https://leetcode.com/problems/knight-probability-in-chessboard/算法

二.題目大意:數組

  給定一個N*N的棋盤和一個初始座標值(r,c),開始時騎士在初始座標處,騎士會進行移動,而且騎士移動的時候這隻能按照以下的移動方式:優化

                             

 

即一共有8個可能移動的方向,而且騎士向每一個方向移動的機率都是相同的(即$1/8$) 。求騎士移動K步後,還在棋盤以內的機率。spa

三.題解:code

  直觀來看,這道題可有用DFS和DP,但不知道DFS會不會超超時,因此我就直接用了DP的思路去解決這個問題。具體以下:
blog

定義一個三維double型數組$dp$,其中$dp[k][i][j]$表示騎士從座標$(i,j)$處開始移動K步後還在棋盤內的機率。很顯然,第K步的結果實收第K-1步的結果影響的,而K-1步的結果可能有8種,因而,能夠寫出狀態轉移方程:leetcode

$$dp[k][i][j] = 1/8(dp[k-1][i - 2][j + 1] + dp[k-1][i - 2][j - 1] + dp[k-1][i - 1][j - 2] + dp[k-1][i - 1][j + 2] + dp[k-1][i + 2][j + 1] + dp[k-1][i + 2][j - 1] + dp[k-1][i + 1][j - 2] + dp[k-1][i + 1][j + 2])$$get

而且當K=0的時候,對於棋盤內全部的座標點的,相應的機率必爲1,因此初始狀態的方程爲:it

$$ dp[0][i][j] = 1$$io

好了,根據這兩個方程,就能夠直接寫代碼了:

 

class Solution
{
public:
    double knightProbability(int N, int K, int r, int c)
    {
        double dp[101][26][26];//dp數組,用於存儲狀態
        int direction[][2] = {{-2,1},{-2,-1},{-1,-2},{-1,2},{2,1},{2,-1},{1,-2},{1,2}};//方向向量,表示8個可能的方向
        if(K == 0)//特殊輸入的判斷
            return 1.0;
        if(r < 0 || c < 0 || c >= N || r >= N)//特殊輸入的判斷
            return 0.0;
        for(int i = 0; i < N; i++)//初始狀態
            for(int j = 0; j < N; j++)
                dp[0][i][j] = 1.0;
        for(int num = 1; num <= K; num++)//注意循環的順序
            for(int i = 0; i < N; i++)
                for(int j = 0; j < N; j++)
                {
                    double tmp = 0;
                    for(int l = 0; l < 8; l++)//分別計算8個可能的方向
                    {
                        int x = i + direction[l][0];
                        int y = j + direction[l][1];
                        if(x < 0 || y <0 || x >= N || y >= N)//不符合條件,則進行下次循環
                            continue;
                        tmp += (1.0 / 8.0)*dp[num - 1][x][y];
                    }

                    dp[num][i][j] = tmp;
                }
        return dp[K][r][c];//返回最終的結果

    }
};

 

  

 

 

該算法的時間複雜度爲O(k*N^2),空間複雜度爲O(K*N^2),應該能夠繼續優化的,但不想繼續作了....

此外,有幾點須要注意的是:

1.最外層循環必須是K,這樣的話才能保證,在求父問題的時候,相應的子問題已經求出結果了。

2.要對每種可能的方向,判斷他們以前是否是還在棋盤內。

相關文章
相關標籤/搜索