688. Knight Probability in Chessboard

Previous674. Longest Continuous Increasing SubsequenceNext689. Maximum Sum of 3 Non-Overlapping Subarrays
Last updated

Last updated
Input: 3, 2, 0, 0
Output: 0.0625
Explanation: There are two moves (to (1,2), (2,1)) that will keep the knight on the board.
From each of those positions, there are also two moves that will keep the knight on the board.
The total probability the knight stays on the board is 0.0625.// Bottom-Up DP
double knightProbability(int N, int K, int r, int c) { // time: O(K * N^2); space: O(N^2)
if (K == 0) return 1.0;
// dp[i][j] means the total number of ways to stay in chessboard from (i, j) after k steps
vector<vector<double> > dp(N, vector<double>(N, 1.0));
vector<vector<int> > dirs({{-2, -1}, {-1, -2}, {-2, 1}, {1, -2}, {-1, 2}, {2, -1}, {2, 1}, {1, 2}});
for (int k = 0; k < K; ++k) {
vector<vector<double> > t(N, vector<double>(N, 0.0));
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
for (auto dir : dirs) {
int x = i + dir[0], y = j + dir[1];
if (x < 0 || x >= N || y < 0 || y >= N) continue;
t[i][j] += dp[x][y];
}
}
}
dp = t;
}
return dp[r][c] / pow(8, K);
}// Top-Down with Memoization
double helper(vector<vector<vector<double> > >& memo, vector<vector<int> >& dirs, int N, int k, int r, int c) {
if (k == 0) return 1.0;
if (abs(memo[k][r][c]) > 1e-6) return memo[k][r][c];
for (auto& dir : dirs) {
int x = r + dir[0], y = c + dir[1];
if (x < 0 || x >= N || y < 0 || y >= N) continue;
memo[k][r][c] += helper(memo, dirs, N, k - 1, x, y);
}
return memo[k][r][c];
}
double knightProbability(int N, int K, int r, int c) { // time: O(K * N^2); space: O(K * N^2)
vector<vector<vector<double> > > memo(K + 1, vector<vector<double> >(N, vector<double>(N, 0.0)));
vector<vector<int> > dirs({{-2, -1}, {-1, -2}, {-2, 1}, {1, -2}, {-1, 2}, {2, -1}, {2, 1}, {1, 2}});
return helper(memo, dirs, N, K, r, c) / pow(8, K);
}