哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级) F 乐乐下象棋 【记忆化搜索】

传送门: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, 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 }

猜你喜欢

转载自www.cnblogs.com/ymzjj/p/10052938.html