题解:P7995 [USACO21DEC] Walking Home B
一道很普通的计数 $\texttt{dp}$。设 $dp_{i,j,k,l}$ 表示在 $(i,j)$ 位置上,还剩下 $k$ 次行走方向改变,当前的方向为 $l$ 时的方案数。因为只能够向下走,则令 $l \in \{0,1\}$ 表示这两种方向。那么显然从起点开始初始化,对于一个草堆的格子,方案数一定为 $0$,对于其它格子,就会有更改方向或不更改方向的两种转移:
1 2 3 4 5 6 7 8
| for (int l = 0;l <= k;++l) { dp[i][j][0][l] += dp[i][j - 1][0][l]; dp[i][j][1][l] += dp[i - 1][j][1][l]; if (l == k) continue; dp[i][j][0][l] += dp[i][j - 1][1][l + 1]; dp[i][j][1][l] += dp[i - 1][j][0][l + 1]; }
|
最后就是答案的统计,根据状态的含义则有 $\sum_{i = 1}^{K} dp_{n,n,i,0} + dp_{n,n,i,1}$。这样就解决了问题,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <queue> #define init(x) memset (x,0,sizeof (x)) #define ll long long #define ull unsigned long long #define INF 0x3f3f3f3f using namespace std; const int MAX = 55; const int MOD = 1e9 + 7; inline int read (); int t,n,k,ans,dp[MAX][MAX][2][5]; char s[MAX][MAX]; int main () { t = read (); while (t--) { n = read ();k = read (); ans = 0; init (dp); for (int i = 1;i <= n;++i) scanf ("%s",s[i] + 1); if (s[1][2] != 'H') dp[1][2][0][k] = 1; if (s[2][1] != 'H') dp[2][1][1][k] = 1; for (int i = 1;i <= n;++i) { for (int j = 1;j <= n;++j) { if (i == 1 && j == 1) continue; if (i == 1 && j == 2) continue; if (i == 2 && j == 1) continue; if (s[i][j] == 'H') continue; for (int l = 0;l <= k;++l) { dp[i][j][0][l] += dp[i][j - 1][0][l]; dp[i][j][1][l] += dp[i - 1][j][1][l]; if (l == k) continue; dp[i][j][0][l] += dp[i][j - 1][1][l + 1]; dp[i][j][1][l] += dp[i - 1][j][0][l + 1]; } } } for (int i = 0;i <= k;++i) ans += dp[n][n][0][i] + dp[n][n][1][i]; printf ("%d\n",ans); } return 0; } inline int read () { int s = 0;int f = 1; char ch = getchar (); while ((ch < '0' || ch > '9') && ch != EOF) { if (ch == '-') f = -1; ch = getchar (); } while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar (); } return s * f; }
|