An improvement is to use (KN^2/8) space for the DP, given than the Chessboard is symmetric. (0, 0), (0, N-1), (N-1,0), (N-1, N-1) will have the same results. Here is my code, using (KN^2/4) space.

class Solution {
vector<pair<int, int> > dirs = {{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
double helper(int N, int K, int r, int c, vector<vector<double> >& dp) {
if (K == 0) return 1.0;
if (r > (N - 1) / 2) r = N - r - 1;
if (c > (N - 1) / 2) c = N - c - 1;
int hN = (N + 1) / 2, key = r * hN + c;
if (dp[key][K - 1] > 0.) return dp[key][K - 1];
dp[key][K - 1] = 0.;
for (auto d : dirs) {
int nx = r + d.first, ny = c + d.second;
if (nx >= 0 && nx < N && ny >= 0 && ny < N) {
dp[key][K - 1] += 0.125 * helper(N, K - 1, nx, ny, dp);
}
}
return dp[key][K - 1];
}
public:
double knightProbability(int N, int K, int r, int c) {
int hN = (N + 1) / 2;
vector<vector<double> > dp = vector<vector<double> >(hN * hN, vector<double> (K, -1.0));
return helper(N, K, r, c, dp);
}
};