传送门:https://ac.nowcoder.com/acm/contest/301/F
题目描述
小乐乐一天天就知道玩,这一天又想玩象棋。
我们都知道马走日。
现在给定一个棋盘,大小是n*m,把棋盘放在第一象限,棋盘的左下角是(0,0),右上角是(n - 1, m - 1);
小乐乐想知道,一个马从左下角(0, 0)开始,走了k步之后,刚好走到右上角(n - 1, m - 1)的方案数。
我们都知道马走日。
现在给定一个棋盘,大小是n*m,把棋盘放在第一象限,棋盘的左下角是(0,0),右上角是(n - 1, m - 1);
小乐乐想知道,一个马从左下角(0, 0)开始,走了k步之后,刚好走到右上角(n - 1, m - 1)的方案数。
输入描述:
输入:多组样例输入,每组一行,三个整数n, m, k(1 <= n, m, k <= 200),如题目所示。
输出描述:
输出:输出答案 mod 1000000007
解题思路:
记忆化搜索(DFS)
dp[ x ][ y ][ s ] 代表第 s 步 走到 x y 的方案数。
搜索的时候记录状态,避免不必要的重复搜索。
细节:
判断 下一步 要走 的 (rx,ry) 是否越界时,如果是判断 越界 那么 条件时 rx >= N || ry >= M (这里每次不一定只走一步)而不是 rx == N || ry == M(这是每次只走一步的情况)。
为了避免这种错误, 还是判断符合的条件比较稳。
AC code:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #define INF 0x3f3f3f3f 7 #define Mod 1000000007 8 #define LL long long 9 using namespace std; 10 const int MAXN = 220; 11 LL dp[MAXN][MAXN][MAXN]; 12 int dvx[] = {2, 2, 1, 1, -2, -2, -1, -1}; 13 int dvy[] = {-1, 1, 2, -2, -1, 1, 2, -2}; 14 LL N, M, K; 15 16 int dfs(int x, int y, int step) 17 { 18 // if(step == K){ 19 // if(x == N-1 && y == M-1) return 1; 20 // else return 0; 21 // } 22 if(dp[x][y][step] != -1) return dp[x][y][step]; 23 int rx, ry; 24 LL res = 0; 25 for(int i = 0; i < 8; i++){ 26 rx = x+dvx[i]; 27 ry = y+dvy[i]; 28 if(rx < 0 || rx >= N || ry < 0 || ry >= M || step >= K) continue; 29 res =(res + dfs(rx, ry, step+1))%Mod; 30 } 31 dp[x][y][step] = res; 32 return res; 33 } 34 35 int main() 36 { 37 LL ans; 38 while(~scanf("%lld%lld%lld", &N, &M, &K)){ 39 memset(dp, -1, sizeof(dp)); 40 dp[N-1][M-1][K] = 1; 41 ans = dfs(0, 0, 0)%Mod; 42 printf("%lld\n", ans); 43 } 44 return 0; 45 }