DP:过河卒

时间:2020-04-17
本文章向大家介绍DP:过河卒,主要包括DP:过河卒使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目描述

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

棋盘用坐标表示,AAA 点 (0,0)(0, 0)(0,0)、BBB 点 (n,m)(n, m)(n,m),同样马的位置坐标是需要给出的。

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

输入格式

一行四个正整数,分别表示 BBB 点坐标和马的坐标。

输出格式

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

输入输出样例

输入 #1
6 6 3 3
输出 #1
6

说明/提示

对于 100%100 \%100% 的数据,1≤n,m≤201 \le n, m \le 201n,m20,0≤0 \le0≤ 马的坐标 ≤20\le 2020。

本人也还是小白,本题的图以及方阵都来自洛谷,仅仅是用于好理解思路,做题,没有其他用途。

主要思路:不难发现每一个格子拥有的路径数(即走不同路径经过这个格子的次数),都是左边和上边格子拥有路径数之和。就所给样例而言:M表示马,A,B表示进出口

 A 0 0 0 0 0 0
 0 0 X 0 X 0 0
 0 X 0 0 0 X 0
 0 0 0 M 0 0 0
 0 X 0 0 0 X 0
 0 0 X 0 X 0 0
 0 0 0 0 0 0 B

然后画出这种情况各点拥有路径情况:

1 1 1 1 1 1 1
1 2 X 1 X 1 2
1 X 0 1 1 X 2
1 1 1 M 1 1 3
1 X 1 1 0 X 3
1 1 X 1 X 0 3
1 2 2 3 3 3 6

很容易就发现规律,每个格子拥有的路径数就是左边和上边格子拥有的路径数之和,对于马的控制区,我们也进行访问,然后判断如果是马的控制区我们至于要把这个点设为0即可。

但是为了防止数组访问越界,我们可以给原有的方阵左边和上边加一列一行0,如图:

0 0 0 0 0 0 0 0 
0 1 1 1 1 1 1 1
0 1 2 X 1 X 1 2
0 1 X 0 1 1 X 2
0 1 1 1 M 1 1 3
0 1 X 1 1 0 X 3
0 1 1 X 1 X 0 3
0 1 2 2 3 3 3 6

这样之后我们就可以轻松的访问了。

初状态: a[1][0] = 1 ,当然 a[0][1] = 1 也没有问题。

递推:  a[i][j] = a[i - 1][j] + a[i][j - 1] 

上边是核心思路。

因为需要判断马的控制区,所以我们可以直接做一个表:

void bj(int mmx, int mmy)  //被马控制的格子
{
    map[mmx][mmy] = 1;
    map[mmx - 2][mmy - 1] = 1;
    map[mmx - 1][mmy - 2] = 1;
    map[mmx + 1][mmy - 2] = 1;
    map[mmx + 2][mmy - 1] = 1;
    map[mmx + 2][mmy + 1] = 1;
    map[mmx + 1][mmy + 2] = 1;
    map[mmx - 1][mmy + 2] = 1;
    map[mmx - 2][mmy + 1] = 1;
}

所以这个题的核心代码就生成啦。

for (int i = 1; i <= x + 1; i++)
{
    for (int j = 1; j <= y + 1; j++)
    {
        a[i][j] = a[i - 1][j] + a[i][j - 1];
            if (map[i - 1][j - 1])
        {
            a[i][j] = 0;
        }
    }
}

至于为什么判断

map[i-1][j-1]而不是map[i][j]

 那是因为我们给整个数组加了一行一列,所以我们当前访问的i,j就是原数组的i-1,j-1。

所以最终代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 
 4 using namespace std;
 5 
 6 unsigned long long x, y, mx, my;
 7 long long a[25][25], map[25][25]; //用来标记
 8 
 9 void bj(int mmx, int mmy)  //被马控制的格子
10 {
11     map[mmx][mmy] = 1;
12     map[mmx - 2][mmy - 1] = 1;
13     map[mmx - 1][mmy - 2] = 1;
14     map[mmx + 1][mmy - 2] = 1;
15     map[mmx + 2][mmy - 1] = 1;
16     map[mmx + 2][mmy + 1] = 1;
17     map[mmx + 1][mmy + 2] = 1;
18     map[mmx - 1][mmy + 2] = 1;
19     map[mmx - 2][mmy + 1] = 1;
20 }
21 
22 int main()
23 {
24     a[1][0] = 1;
25     cin >> x >> y >> mx >> my; 
26 
27     bj(mx, my); //调用标记函数
28     for (int i = 1; i <= x + 1; i++)
29     {
30         for (int j = 1; j <= y + 1; j++)
31         {
32             a[i][j] = a[i - 1][j] + a[i][j - 1];
33             if (map[i - 1][j - 1])
34             {
35                 a[i][j] = 0;
36             }
37         }
38     }
39 
40     cout << a[x + 1][y + 1];
41     return 0;
42 }

原文地址:https://www.cnblogs.com/ZhengLijie/p/12720819.html