题目描述
棋盘上\(A\)点有一个过河卒,需要走到目标\(B\)点。卒行走的规则:可以向下、或者向右。同时在棋盘上\(C\)点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,\(A\)点\((0, 0)\)、\(B\)点\((n, m)\)(\(n\), \(m\)为不超过\(20\)的整数),同样马的位置坐标是需要给出的。
现在要求你计算出卒从\(A\)点能够到达\(B\)点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入输出格式
输入格式:
一行四个数据,分别表示\(B\)点坐标和马的坐标。
输出格式:
一个数据,表示所有的路径条数。
输入输出样例
输入样例#1:
6 6 3 3 ## 输出样例#1: 6 # 说明 结果可能很大! * * *
看到题目二话不说用了搜索,直到在提交前看了一下算法标签,又看了一下数据范围。。。
状态转移方程的推导并不复杂,每次判断卒是否能走到这个格子,不可以则为0(显而易见),可以则为下方与左方的值之和。
上代码,这道题算是一道DP入门题吧。
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
| #include<stdio.h>
const int MAXN = 20 + 5; const int attack[9][2] = {{0, 0}, {1, 2}, {2, 1}, {-1, 2}, {2, -1}, {1, -2}, {-2, 1}, {-1, -2}, {-2, -1}}; long long dist[MAXN][MAXN]; int map[MAXN][MAXN]; int n, m, x, y;
void init(void) { for(int i = 0; i < 9; i++) { if(x + attack[i][0] <= n && x + attack[i][0] >= 0) { if(y + attack[i][1] <= m && y + attack[i][1] >= 0) { map[x + attack[i][0]][y + attack[i][1]] = true; } } } }
int main() { scanf("%d%d%d%d", &n, &m, &x, &y); init(); int k = 1; for(int i = 0; i <= n; i++) { dist[i][0] = map[i][0] ? k = 0 : k; } k = 1; for(int i = 0; i <= m; i++) { dist[0][i] = map[0][i] ? k = 0 : k; } for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { dist[i][j] = map[i][j] ? 0 : dist[i - 1][j] + dist[i][j - 1]; } } printf("%lld\n", dist[n][m]); return 0; }
|