LeetCode/cpp/knight-dialer.cpp

77 lines
1.7 KiB
C++
Raw Permalink Normal View History

#include <array>
#include <cstdint>
#include <numeric>
#include <vector>
class Solution {
using pad_t = std::array<int, 12>;
static bool isValidMove(int i) {
return i >= 0 && i < 12 && i != 9 && i != 11;
}
static int index(int x, int y) {
if (x < 0 || x >= 3 || y < 0 || y >= 4) {
return -1;
}
return y * 3 + x;
}
static int add(int x, int y) { return (x + y) % 1000000007; }
static int get(const std::vector<pad_t> &dp, int it, int idx) {
if (it < 0 || it >= static_cast<int>(dp.size())) {
return 0;
}
if (!isValidMove(idx)) {
return 0;
}
return dp[it][idx];
}
static void dpIteration(std::vector<pad_t> &dp, int it) {
for (int i = 0; i < 12; ++i) {
if (!isValidMove(i)) {
continue;
}
int dx = -2, dy = -1;
for (int j = 0; j < 8; ++j) {
auto next = index(i % 3 + dx, i / 3 + dy);
dp[it][i] = add(dp[it][i], get(dp, it - 1, next));
// adjustment of the dx, dy
dy *= -1;
if (j % 2 == 1) {
dx *= -1;
}
if (j % 4 == 3) {
int d = dx;
dx = dy;
dy = d;
}
}
}
}
public:
int knightDialer(int n) {
std::vector<pad_t> dp(n);
dp[0].fill(1);
dp[0][9] = 0;
dp[0][11] = 0;
for (int i = 1; i < n; ++i) {
dpIteration(dp, i);
}
return std::accumulate(dp.back().begin(), dp.back().end(), 0, add);
}
};