题目描述
棋盘上 �A 点有一个过河卒,需要走到目标 �B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 �C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,�A 点 (0,0)(0,0)、�B 点 (�,�)(n,m),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 �A 点能够到达 �B 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入格式
一行四个正整数,分别表示 �B 点坐标和马的坐标。
输出格式
一个整数,表示所有的路径条数。
输入输出样例
输入 #1
6 6 3 3
输出 #1
6
说明/提示
对于 100%100% 的数据,1≤�,�≤201≤n,m≤20,0≤0≤ 马的坐标 ≤20≤20。
【题目来源】
NOIP 2002 普及组第四题
没什么可说的,讲解都在代码里
注意:本题答案很大,需要用到 long long
【AC 代码】:
#include <bits/stdc++.h>
using namespace std;
/*
1.标记马的点,和马所有走过的点,把他们设为 0
[
标记马的位置:
1.当前位置
2.[i - 1, j - 2] 3.[i - 2, j - 1] 4.[i - 2, j + 1]
5.[i - 1, j + 2] 6.[i + 1, j - 2] 7.[i + 2, j - 1] 8.[i + 1, j + 2]
9.[i + 2, j + 1]
]
2.如果 i == 0,当前值就等于 = 左面的值
3.如果 j == 0, 当前值就等于 = 上面的值
4.其余点等于 = 左面的值 + 上面的值
*/
int n, m, x, y;
long long a[150][150];
//n, m 表示这个棋盘的行数和列数
//x, y 表示马的行数和列数
void vis(int i, int j) {
if (i - 1 >= 0 && j - 2 >= 0) a[i - 1][j - 2] = 0;
if (i - 2 >= 0 && j + 1 >= 0) a[i - 2][j + 1] = 0;
if (i - 2 >= 0 && j - 1 <= m) a[i - 2][j - 1] = 0;
if (i - 1 >= 0 && j + 2 <= m) a[i - 1][j + 2] = 0;
if (i + 1 <= n && j - 2 >= 0) a[i + 1][j - 2] = 0;
if (i + 2 <= n && j - 1 >= 0) a[i + 2][j - 1] = 0;
if (i + 1 <= n && j + 2 <= m) a[i + 1][j + 2] = 0;
if (i + 2 <= n && j + 1 <= m) a[i + 2][j + 1] = 0;
}
int main() {
cin >> n >> m >> x >> y;
//读入棋盘的大小 以及 马的坐标
for (int i = 0; i <= n; i++)
for (int j = 0; j <= m; j++)
a[i][j] = 1; //把所有位置标记为 1
//把马的位置以及走到的位置标记成 0
a[x][y] = 0;
vis(x, y);
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++) {
//如果是 第一个 或 这个点为马走过的点 ,则跳过
if ((i == 0 && j == 0) || (a[i][j] == 0))
continue;
//i == 0, 当前值就等于 = 左面的值
if (i == 0)
a[i][j] = a[i][j - 1];
//j == 0, 当前值就等于 = 上面的值
else if (j == 0)
a[i][j] = a[i - 1][j];
//其他值 = 左面的值 + 上面的值
else
a[i][j] = a[i][j - 1] + a[i - 1][j];
}
}
//输出答案
cout << a[n][m] << endl;
}