76 lines
1.7 KiB
C++
76 lines
1.7 KiB
C++
#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);
|
|
}
|
|
};
|