Description
国际象棋中的马放在一个拨号器的任意位置,求走
1 2 3
4 5 6
7 8 9
* 0 #
拨号器如上表所示(其中*
和#
不可用)。
另外补充马的走法,如上图所示。
Constraints
Solution
没啥意思的题目,思路见LeetCode-688,仅需消除后效性。
我本以为需要做一个转换表,比如
偶尔用点离谱的写法当题解吧。
Code
class Solution {
public:
int knightDialer(int n) {
constexpr int dx[] = {-2, -1, 1, 2, 2, 1, -1, -2};
constexpr int dy[] = {-1, -2, -2, -1, 1, 2, 2, 1};
long dp[2][3][4] {};
fill(&dp[0][0][0], &dp[1][0][0], 1);
dp[0][0][3] = dp[0][2][3] = 0;
auto for_d = [&](int i, int j, auto &&f) {
for(auto d = 0; d < 8; ++d) {
auto x = i + dx[d];
auto y = j + dy[d];
if(x < 0 || x >= 3) continue;
if(y < 0 || y >= 4) continue;
f(x, y);
}
};
constexpr long MOD = 1e9 + 7;
for(int step = 1; step < n; ++step) {
auto zip = [](auto &i, auto &j) {++(j==3?j=0,i:j);};
for(int i = 0, j = 0; i < 3; zip(i, j)) {
dp[step &1][i][j] = 0;
if(i == 0 && j == 3) continue;
if(i == 2 && j == 3) continue;
for_d(i, j, [&](auto x, auto y) {
dp[step &1][i][j] += dp[step-1 &1][x][y];
dp[step &1][i][j] %= MOD;
});
}
}
long sum = 0;
for(auto &&vec : dp[n-1&1]) {
sum = accumulate(begin(vec), end(vec), sum % MOD);
}
return sum % MOD;
}
};