码迷,mamicode.com
首页 > 其他好文 > 详细

LeetCode——688. Knight Probability in Chessboard

时间:2018-08-02 15:59:54      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:problem   题解   alt   return   初始   有用   计算   图片   [1]   

一.题目链接:https://leetcode.com/problems/knight-probability-in-chessboard/

二.题目大意:

  给定一个N*N的棋盘和一个初始坐标值(r,c),开始时骑士在初始坐标处,骑士会进行移动,并且骑士移动的时候这只能按照如下的移动方式:

                             技术分享图片

 

即一共有8个可能移动的方向,并且骑士向每个方向移动的概率都是相同的(即$1/8$) 。求骑士移动K步后,还在棋盘之内的概率。

三.题解:

  直观来看,这道题可有用DFS和DP,但不知道DFS会不会超超时,所以我就直接用了DP的思路去解决这个问题。具体如下:

定义一个三维double型数组$dp$,其中$dp[k][i][j]$表示骑士从坐标$(i,j)$处开始移动K步后还在棋盘内的概率。很显然,第K步的结果实收第K-1步的结果影响的,而K-1步的结果可能有8种,于是,可以写出状态转移方程:

$$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])$$

并且当K=0的时候,对于棋盘内所有的坐标点的,相应的概率必为1,所以初始状态的方程为:

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

好了,根据这两个方程,就可以直接写代码了:

 

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.要对每种可能的方向,判断他们之前是不是还在棋盘内。

 

LeetCode——688. Knight Probability in Chessboard

标签:problem   题解   alt   return   初始   有用   计算   图片   [1]   

原文地址:https://www.cnblogs.com/wangkundentisy/p/9407127.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!