#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);
    }
};