题目描述
棋盘上A点有一个过河卒,需要走到目标BB点。卒行走的规则:可以向下、或者向右。同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,A点(0, 0)、B点(n, m)(n, m为不超过20的整数),同样马的位置坐标是需要给出的。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int x = in.nextInt(),y = in.nextInt(),x1 = in.nextInt(),y1 = in.nextInt();
long[][] a = new long[25][25];
int[][] g = new int[25][25];
g[x1][y1] = 1;
//记录 这8 个if 是将所有被马控制 点标记为1
if (x1 >1 && y1 > 0) {
g[x1-2][y1-1] = 1;
}
if (x1 >0 && y1 > 1) {
g[x1-1][y1-2] = 1;
}
if (x1 > 1 && y1 < 20) {
g[x1-2][y1+1] =1;
}
if (x1 > 0 && y1 < 19) {
g[x1-1][y1+2] = 1;
}
if (x1 < 20 && y1 > 1) {
g[x1+1][y1-2] = 1;
}
if (x1 < 19 && y1 > 0) {
g[x1+2][y1-1] = 1;
}
if (x1 < 20 && y1 < 19) {
g[x1+1][y1+2] = 1;
}
if (x1 < 19 && y1 < 20) {
g[x1+2][y1+1] = 1;
}
for (int i = 0; i <= x; i++) {
for (int j = 0; j <= y; j++) {
if (g[i][j] == 0) { // 二维表的初始值都为0,如果控制点的位置为1,那么这个格子就为0 ,也就是继续执行。这个格子后面的格子的最后一步只能向右或下到达,这个格子被占了的话,那么从这个格子到后面格子的路径数位0,只能看右边格子的上面格子数的路径。
if (i == 0 && j == 0) {
a[0][0] = 1;
} else if (i == 0 && j > 0) {
a[0][j] = a[0][j - 1];
} else if (j == 0 && i > 0) {
a[i][0] = a[i-1][0];
} else {
a[i][j] = a[i-1][j] + a[i][j-1]
}
}
}
}
System.out.println(a[x][y]);
}
}
C语言的也差不多,就不写了,这也是看了其他大佬的。
注意一点是 这个走格子和走点是一样的,
以输入样例 6×6,马在 (3,3) 为例,左至右分别为 x,上至下分别为 y。
下面顺便对样例进行一下解释:
其中 PP 点为马的控制点。我们不妨把马的控制点 g[x][y]g[x][y] 标记为 1。
样例共有 6 条路径
大家仔细观察一下,马在第一排 (y=0)(y=0) 的走法有三种:
第一排走到底,再走到目标点;
第一排走到第四个 0 的位置,这里大家可以看出有一种路径;
第一排走到倒数第二个 0 的位置,拐个弯到达目标位置;
这里总共 3 种走法; 在第一列 (x=0)(x=0) 的走法有两种,分别是:
第一列走到倒数第二个 0 的位置,拐个弯到达目标位置;
第一列走到第四个 0 的位置,大家可以看出有一种路径;
第一列走到底,再走到目标点;
这里总共有 3 种走法;加上前面的3种,共有6种!
看到这里,大家应该明白了题意,现在我们看输入输出:
输入前两个数,为棋盘的长宽;
输入后两个数,为马的坐标
(
x
,
y
)
(x,y)
(x,y);
这里告诉大家一个公式(证明度娘)
在平面内,从点 (0,0)(0,0) 到点 (x,y)(x,y) 的路径数f[x][y]=f[x-1][y]+f[x][y-1]f[x][y]=f[x−1][y]+f[x][y−1]
现在解释一下:其实就是一个简单的 DPDP 方程(或者说递推式),到达一个点 (x,y)(x,y),可能从 (x-1,y)(x−1,y) 或者 (x,y-1)(x,y−1) 走来,因此方案数为到 (x-1,y)(x−1,y) 和到 (x,y-1)(x,y−1) 方案的总和。
然后就可以愉快的开始搜索了,思路有两种:
dfs 深搜+回溯(即递归搜索)
递推(或者说是 DPDP)
不论是递推或是递归,都要确定边界:
根据上述公式,数组不能越界对吧?
递推:
若 x=0x=0,则 f[x][y]=f[0][y-1]f[x][y]=f[0][y−1](自己画图思考一下)
若 y=0y=0,则 f[x][y]=f[x-1][0]f[x][y]=f[x−1][0]
当 g[x][y]=1g[x][y]=1 的时候,肯定不能搜索啦(f[x][y]=0f[x][y]=0 )
最后,写个 else (上述公式) 就好了
上面的方法是对于如果只是从某一个点到另一个点的路径数的总和,没有什么不能经过的点。
这里还要提个醒:这题不需要高精,long 就可以了!(讲解部分为大佬的,确实很好了)