zoukankan      html  css  js  c++  java
  • LeetCode——688. Knight Probability in Chessboard

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

  • 相关阅读:
    javaweb学习总结(二十一)——JavaWeb的两种开发模式
    javaweb学习总结(二十)——JavaBean总结
    javaweb学习总结(十九)——JSP标签
    javaweb学习总结(十八)——JSP属性范围
    JavaWeb学习总结(十七)——JSP中的九个内置对象
    javaweb学习总结(十六)——JSP指令
    javaweb学习总结(十五)——JSP基础语法
    javaweb学习总结(十四)——JSP原理
    JavaWeb学习总结(十三)——使用Session防止表单重复提交
    JavaWeb学习总结(十二)——Session
  • 原文地址:https://www.cnblogs.com/wangkundentisy/p/9407127.html
Copyright © 2011-2022 走看看