【题目描述】
棋盘上 A A A点有一个过河卒,需要走到目标 B B B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的某一点有一个对方的马(如 C C C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如下图中的 C C C点和 P 1 , … … , P 8 P1,……,P8 P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示, A A A点 ( 0 , 0 ) (0,0) (0,0)、 B B B点 ( n , m ) (n, m) (n,m) ( n , m n,m n,m为不超过 20 20 20的整数),同样马的位置坐标是需要给出的, C ≠ A C≠A C=A且 C ≠ B C≠B C=B。现在要求你计算出卒从 A A A点能够到达 B B B点的路径的条数。
【输入】
给出 n n n、 m m m和 C C C点的坐标。
【输出】
从 A A A点能够到达 B B B点的路径的条数。
【解题思路】
- 定义二值化地图 a [ 100 ] [ 100 ] a[100][100] a[100][100],马的控制位置一共 9 9 9个点,设置为 1 1 1,代表不可通行节点;其余均为 0 0 0,代表可以通行。
- 定义路径条数存储的地图 b [ 100 ] [ 100 ] b[100][100] b[100][100],其中每个数值均为地图中该点到 A A A点的可行路径条数。为了防止到 b [ − 1 ] [ 0 ] b[-1][0] b[−1][0]这种越界的情况,把输入 n , m , C x , C y n,m,Cx,Cy n,m,Cx,Cy均 + 1 +1 +1处理。
- 初始化 b [ 1 ] [ 1 ] b[1][1] b[1][1]为 1 1 1,即 A A A点到 A A A点有一条路径(假设情况),从而后边就可以通过递推公式 b [ i ] [ j ] = b [ i − 1 ] [ j ] + b [ i ] [ j − 1 ] b[i][j]=b[i-1][j]+b[i][j-1] b[i][j]=b[i−1][j]+b[i][j−1] 得到,注意如果遇到不可通行节点,则 b [ i ] [ j ] = 0 b[i][j]=0 b[i][j]=0。
- 最后输出 b [ n ] [ m ] b[n][m] b[n][m]即为 B B B点到 A A A点的可通行路径条数(并非 b [ n − 1 ] [ m − 1 ] b[n-1][m-1] b[n−1][m−1],因为我们对 n , m n,m n,m已经进行过 + 1 +1 +1操作了)。
【解题代码】
#include <bits/stdc++.h>
using namespace std;
bool a[100][100];
long long b[100][100];
int main() {
int n,m,Cx,Cy;
cin >> n >> m >> Cx >> Cy;
n += 1, m += 1, Cx += 1, Cy += 1; //所有坐标+1,防止越界
//设置马的控制位置全为1
a[Cx][Cy] = 1;
a[Cx - 1][Cy + 2] = 1;
a[Cx - 1][Cy - 2] = 1;
a[Cx - 2][Cy + 1] = 1;
a[Cx - 2][Cy - 1] = 1;
a[Cx + 1][Cy + 2] = 1;
a[Cx + 1][Cy - 2] = 1;
a[Cx + 2][Cy + 1] = 1;
a[Cx + 2][Cy - 1] = 1;
//设置初始位置为1,进行动态规划递推
b[1][1] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i == 1 && j == 1) {
j++;
}
if (a[i][j] == 0) {
b[i][j] = b[i - 1][j] + b[i][j - 1];
}
}
}
cout << b[n][m];
return 0;
}