过河卒问题求解

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

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

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

输入格式

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

输出格式

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

输入输出样例

输入 

6 6 3 3

输出 

6

说明/提示

对于 100%100% 的数据,1≤n,m≤201≤n,m≤20,0≤0≤ 马的坐标 ≤20≤20。

求解

#include <stdio.h>
#include <string.h>

#define MAXN 21 // 定义棋盘的最大尺寸

int dp[MAXN][MAXN]; // 动态规划数组,dp[i][j]表示到达点(i, j)的路径数
int horse[MAXN][MAXN]; // 标记马的控制点,horse[i][j]为1表示点(i, j)是马的控制点
int n, m, x, y; // n和m是目标点B的坐标,x和y是马的坐标

// 初始化马的控制点
void initHorse() {
    memset(horse, 0, sizeof(horse)); // 初始化horse数组为0
    horse[x][y] = 1; // 马的位置也是控制点
    // 马的八种走法,用数组表示
    int moves[8][2] = {{2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}, {1, -2}, {2, -1}};
    for (int i = 0; i < 8; i++) {
        int nx = x + moves[i][0], ny = y + moves[i][1]; // 计算马走一步后的新位置
        // 检查新位置是否在棋盘内,如果在则标记为马的控制点
        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
            horse[nx][ny] = 1;
        }
    }
}

int main() {
    scanf("%d %d %d %d", &n, &m, &x, &y); // 读取输入
    memset(dp, 0, sizeof(dp)); // 初始化dp数组为0
    dp[0][0] = 1; // 起点(0, 0)的路径数为1
    initHorse(); // 初始化马的控制点

    // 动态规划计算到达每个点的路径数
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            // 如果当前点不是马的控制点
            if (i > 0 && !horse[i-1][j]) dp[i][j] += dp[i-1][j]; // 从左边来
            if (j > 0 && !horse[i][j-1]) dp[i][j] += dp[i][j-1]; // 从上面来
        }
    }

    printf("%d\n", dp[n][m]); // 输出到达目标点B的路径数
    return 0;
}

详细注释解释

  • #define MAXN 21:定义了一个常量MAXN,表示棋盘的最大尺寸,这里假设棋盘的大小不超过20x20。
  • int dp[MAXN][MAXN]:声明了一个二维数组dp,用于存储动态规划的结果,dp[i][j]表示到达点(i, j)的路径数。
  • int horse[MAXN][MAXN]:声明了一个二维数组horse,用于标记马的控制点。
  • int n, m, x, y;:声明了四个整型变量,分别用于存储目标点B的坐标(n, m)和马的坐标(x, y)。
  • void initHorse():定义了一个函数initHorse,用于初始化马的控制点。
  • memset(horse, 0, sizeof(horse));:使用memset函数将horse数组初始化为0,表示棋盘上的所有点最初都不是马的控制点。
  • horse[x][y] = 1;:将马的位置标记为控制点。
  • int moves[8][2]:定义了一个二维数组moves,包含了马的八种走法。
  • if (nx >= 0 && nx < n && ny >= 0 && ny < m):检查马走一步后的新位置是否在棋盘内,如果在,则将其标记为马的控制点。
  • memset(dp, 0, sizeof(dp));:将dp数组初始化为0。
  • dp[0][0] = 1;:起点(0, 0)的路径数为1。
  • initHorse();:调用initHorse函数初始化马的控制点。
  • for (int i = 0; i <= n; i++):外层循环遍历棋盘的每一行。
  • for (int j = 0; j <= m; j++):内层循环遍历棋盘的每一列。
  • if (i > 0 && !horse[i-1][j]) dp[i][j] += dp[i-1][j];:如果当前点不是马的控制点,且可以从左边的点到达,则累加路径数。
  • if (j > 0 && !horse[i][j-1]) dp[i][j] += dp[i][j-1];:如果当前点不是马的控制点,且可以从上面的点到达,则累加路径数。
  • printf("%d\n", dp[n][m]);:输出到达目标点B的路径数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值