1. 程式人生 > >哈爾濱理工大學軟體與微電子學院第八屆程式設計競賽同步賽(高年級) F 樂樂下象棋 【記憶化搜尋】

哈爾濱理工大學軟體與微電子學院第八屆程式設計競賽同步賽(高年級) 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 }