leetcode算法題--“馬”在棋盤上的概率★

原題鏈接:https://leetcode-cn.com/problems/knight-probability-in-chessboard/

1、遞歸
代碼:

double knightProbability(int N, int K, int r, int c) {
   return knightCounts(N,K,r,c)/pow(8,K);
}

int knightCounts(int N, int K, int r, int c){
    if(r<0||r>N-1||c<0||c>N-1) return 0;
    if(K==0) return 1;
    return knightCounts(N,K-1,r-2,c-1)+knightCounts(N,K-1,r-2,c+1)+knightCounts(N,K-1,r+2,c-1)+knightCounts(N,K-1,r+2,c+1)+knightCounts(N,K-1,r+1,c-2)+knightCounts(N,K-1,r-1,c-2)+knightCounts(N,K-1,r+1,c+2)+knightCounts(N,K-1,r-1,c+2);
}

但是超時了!

2、動態規劃

double knightProbability(int N, int K, int r, int c) {
    double total=pow(8,K);
    vector<vector<vector<int>>> dp(N,vector<vector<int>>(N,vector<int>(K+1,0)));
    dp[r][c][K]=1;
    while(K){
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                while(dp[i][j][K]--){
                    if(i-2>=0&&j-1>=0) dp[i-2][j-1][K-1]+=1;
                    if(i-2>=0&&j+1<N) dp[i-2][j+1][K-1]+=1;
                    if(i+2<N&&j-1>=0) dp[i+2][j-1][K-1]+=1;
                    if(i+2<N&&j+1<N) dp[i+2][j+1][K-1]+=1;
                    if(i-1>=0&&j+2<N) dp[i-1][j+2][K-1]+=1;
                    if(i-1>=0&&j-2>=0) dp[i-1][j-2][K-1]+=1;
                    if(i+1<N&&j+2<N) dp[i+1][j+2][K-1]+=1;
                    if(i+1<N&&j-2>=0) dp[i+1][j-2][K-1]+=1;
                }
            }
        }
        K--;
    }
    int count=0;
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            if(dp[i][j][0]){
                count+=dp[i][j][0];
            }
        }
    }
    return count/total;
}

還是超時,因爲我這個動態規劃並沒有動態規劃的精髓

3、動態規劃+記憶化
當我們想計算(r,c)有多少走法時,可以反向思考,有多少點可以走到(r,c)點,所以也就不難理解下面的狀態轉移

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

表示從位置(r,c)走k步,馬仍然在棋盤上的概率<==>從棋盤上其他位置,走k步到(r,c)的概率。

double knightProbability(int N, int K, int r, int c) {
   if(N==0) return 0;
   vector<vector<vector<double>>> dp(N+4,vector<vector<double>>(N+4,vector<double>(K+1,0)));
   for(int i=0;i<N+4;i++){
       for(int j=0;j<N+4;j++){
           if(i>=2&&i<N+2&&j>=2&&j<N+2){
               dp[i][j][0]=1;
           }
       }
   }
   for(int k=1;k<=K;k++){
       for(int i=2;i<N+2;i++){
           for(int j=2;j<N+2;j++){
               dp[i][j][k]=(dp[i-2][j-1][k-1]+dp[i-2][j+1][k-1]+dp[i+2][j-1][k-1]+dp[i+2][j+1][k-1]+\
                            dp[i-1][j+2][k-1]+dp[i-1][j-2][k-1]+dp[i+1][j+2][k-1]+dp[i+1][j-2][k-1])/8.0;
           }
       }
   }
   return dp[r+2][c+2][K];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章