P1002 过河卒

题目描述

棋盘上AA点有一个过河卒,需要走到目标BB点。卒行走的规则:可以向下、或者向右。同时在棋盘上CC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。

棋盘用坐标表示,AA点(0, 0)(0,0)、BB点(n, m)(n,m)(nn, mm为不超过2020的整数),同样马的位置坐标是需要给出的。

现在要求你计算出卒从AA点能够到达BB点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。

输入输出格式

输入格式:

 

一行四个数据,分别表示BB点坐标和马的坐标。

 

输出格式:

 

一个数据,表示所有的路径条数。

输入输出样例

输入样例#1: 
6 6 3 3
输出样例#1: 
6

说明

结果可能很大!

分析:

思路:    不难想到状态转移方程(请手算模拟样例),设num[i][j]表示第i行第j列的可达路径总数,则对于非边界坐标,都有num[i][j] = num[i-1][j] + num[i][j-1]成立。

            对于马的控制点(包括马所在的位置)x, y要使num[x][y] = 0表示不可达,这样做还有一个好处是不会影响到上述递推式的正确性。

注意点:1.题目明确提示应该至少开一个long long二维数组来记录num[][]

    2.注意要判断马的控制点是否数组越界和越过(0,0)到(n, m)标识的范围内

    3.注意在给第0行以及第0列赋初值时,如果未遇到马的控制点,则赋值为1,一旦遇到了则之后全部为0(在程序中可以直接break)

AC代码:

 1 #include 
12 using namespace std;
13 typedef unsigned long long ULL;
14 const int MAXV = 20 + 10;
15 ULL num[MAXV][MAXV];
16 int n, m, dx, dy; // B点坐标和马的坐标
17 bool not_arrive[MAXV][MAXV] = {false};
18 const int X[] = {0, 1, 2, 2, 1, -1, -2, -2, -1};
19 const int Y[] = {0, -2, -1, 1, 2, 2, 1, -1, -2};
20 bool ok_loc(int x, int y) {
21     if (x < 0 || x > m || y < 0 || y > n) return false;
22     return true; 
23 }  
24 
25 int main() {
26     //ios::sync_with_stdio(false);
27     scanf("%d %d %d %d", &n, &m, &dx, &dy);
28     for (int i = 0; i < 9; i++) {
29         int x = dx + X[i], y = dy + Y[i];
30         if (ok_loc(x, y)) not_arrive[x][y] = true;
31     }
32     for (int i = 0; i <= n; i++) { // 0列n行 
33         if (!not_arrive[i][0]) num[i][0] = 1;
34         else break;
35     }
36     for (int i = 0; i <= m; i++) { // m列0行 
37         if (!not_arrive[0][i]) num[0][i] = 1;
38         else break;
39     }
40     for (int i = 1; i <= n; i++) {
41         for (int j = 1; j <= m; j++) {
42             if (not_arrive[i][j]) num[i][j] = 0;
43             else num[i][j] = num[i][j-1] + num[i-1][j];
44         }
45     }
46     printf("%llu\n", num[n][m]);
47     
48     
49     return 0;
50 }

 

转载于:https://www.cnblogs.com/Shiko/p/10698431.html

你可能感兴趣的:(P1002 过河卒)