棋盘上 A A A 点有一个过河卒,需要走到目标 B B B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C C C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示, A A A 点 ( 0 , 0 ) (0, 0) (0,0)、 B B B 点 ( n , m ) (n, m) (n,m),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 A A A 点能够到达 B B B 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
一行四个正整数,分别表示 B B B 点坐标和马的坐标。
一个整数,表示所有的路径条数。
6 6 3 3
6
对于 100 % 100 \% 100% 的数据, 1 ≤ n , m ≤ 20 1 \le n, m \le 20 1≤n,m≤20, 0 ≤ 0 \le 0≤ 马的坐标 ≤ 20 \le 20 ≤20。
【题目来源】
NOIP 2002 普及组第四题
#include<iostream>
using namespace std;
const int N = 35;
const int dx[8] = { 1,1,-1,-1,2,2,-2,-2 };
const int dy[8] = { 2,-2,2,-2,1,-1,1,-1 };
long long f[N][N] = { 0 }; //f[i][j] 代表从0,0到i,j的路线数量
int n, m, x, y;
bool vis[N][N];
int main() {
cin >> n >> m >> x >> y;
vis[0][0] = 1; //标记入点
vis[x][y] = 1; //标记马的位置
for (int i = 0; i < 8; i++) { //标记马的控制点,记住防越界
int xx = x + dx[i], yy = y + dy[i];
if(xx >= 0 && xx <= n && yy >= 0 && yy <= m)
vis[xx][yy] = 1;
}
f[0][0] = 1; //把0,0点初始化为1
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++) { //要判断是否越界
if (!vis[i][j]) {
if (i - 1 < 0) {
f[i][j] = f[i][j - 1];
}else
if (j - 1 < 0) {
f[i][j] = f[i - 1][j];
}
else {
f[i][j] = f[i - 1][j] + f[i][j - 1];//由于只能往下走或者往右走,所以为两个方向走过来的数量加起来
}
}
}
}
cout << f[n][m];
return 0;
}