P1002. 过河卒

考点

  • 线性动态规划

题解

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
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll f[25][25], ctrl[25][25], n, m, hx, hy;

void init()
{
ctrl[hx][hy] = 1;
for (int i = -2; i <= 2; ++i)
for (int j = -2; j <= 2; ++j)
if (abs(i) + abs(j) == 3 &&
(hx + i) >= 0 && (hx + i) <= n &&
(hy + j) >= 0 && (hy + j) <= m)
ctrl[hx + i][hy + j] = 1;
}

void run()
{
for (int i = 0; i <= n; ++i)
{
for (int j = 0; j <= m; ++j)
{
if (ctrl[i][j])
continue;
if (i - 1 >= 0 && i - 1 <= n)
f[i][j] += f[i - 1][j];
if (j - 1 >= 0 && j - 1 <= m)
f[i][j] += f[i][j - 1];
}
}
cout << f[n][m];
}

int main()
{
f[0][0] = 1;
cin >> n >> m >> hx >> hy;
init(), run();
return 0;
}

思路

每次只能向右和向下走,那么每个新的状态就只能由上面一个点和左边一个点共同组成,很容易得到递推式: \[ f\left( x,y \right) =f\left( x-1,y \right) +f\left( x,y-1 \right) \] 由于需要避开马的控制范围,所以单独开一个数组ctrl,记录哪些点不能走即可