递归DP-走step步后仍在一个区域的概率问题

2022-6-12 diaba 笔试题

package com.jiucaiyuan.net.question;

/**
 * @Author jiucaiyuan  2022/6/5 23:00
 * @mail services@jiucaiyuan.net
 */

public class BobWalkOnGrid {

    /**
     * 在N*M的区域范围内,Bob在(i,j)位置,走step步之后,仍然在区域内的点数
     *
     * @param N
     * @param M
     * @param i
     * @param j
     * @param k
     * @return
     */
    public static double bob1(int N, int M, int i, int j, int k) {
        //所有走法数目
        long all = (long) Math.pow(4, k);
        System.out.println("all=" + all);

        //走完k步后,bob仍然在区域中的走法数目
        long live = process(N, M, i, j, k);
        System.out.println("live=" + live);
        //最大公约数
        long gcd = gcd(all, live);
        System.out.println("gcd=" + gcd);
        return (double) live / all;
    }

    /**
     * 求m和n的最大公约数
     *
     * @param m
     * @param n
     * @return
     */
    public static long gcd(long m, long n) {
        return n == 0 ? m : gcd(n, m % n);
    }

    private static long process(int N, int M, int i, int j, int step) {
        System.out.println("i=" + i + ",j=" + j + ",step=" + step);
        if (i < 0 || i == N || j < 0 || j == M) {
            //当前Bob已经在N*M区域外
            return 0;
        }
        //如果走完了,未出界,存活
        if (step == 0) {
            System.out.println("已经走完了");
            return 1;
        }
        long live = process(N, M, i - 1, j, step - 1);
        live += process(N, M, i + 1, j, step - 1);
        live += process(N, M, i, j - 1, step - 1);
        live += process(N, M, i, j + 1, step - 1);

        return live;
    }

    public static double dpBob(int N, int M, int row, int col, int k) {
        long[][][] dp = new long[N][M][k + 1];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                dp[i][j][0] = 1;
            }
        }
        for (int rest = 1; rest <= k; rest++) {
            for (int r = 0; r < N; r++) {
                for (int c = 0; c < M; c++) {
                    dp[r][c][rest] = pick(dp, N, M, r - 1, c, rest - 1);
                    dp[r][c][rest] += pick(dp, N, M, r + 1, c, rest - 1);
                    dp[r][c][rest] += pick(dp, N, M, r, c - 1, rest - 1);
                    dp[r][c][rest] += pick(dp, N, M, r, c + 1, rest - 1);
                }
            }
        }
        return (double) dp[row][col][k] / Math.pow(4, k);
    }

    public static long pick(long[][][] dp, int N, int M, int r, int c, int rest) {
        if (r < 0 || r == N || c < 0 || c == M) {
            return 0;
        }
        return dp[r][c][rest];
    }

    public static void main(String[] args) {
        System.out.println("bob1");
        int k = 30;
        //System.out.println(bob1(6, 6, 3, 4, k));  //跑的太慢了
        System.out.println("dpBob");
        System.out.println(dpBob(6, 6, 3, 4, k));
    }

}

发表评论:

Powered by emlog 京ICP备15045175号-1 Copyright © 2022