题解:洛谷 P1002 [NOIP 2002 普及组] 过河卒

【题目来源】

洛谷:P1002 [NOIP 2002 普及组] 过河卒 - 洛谷 (luogu.com.cn)

【题目描述】

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

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

image

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

【输入】

一行四个正整数,分别表示 \(B\) 点坐标和马的坐标。

【输出】

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

【输入样例】

6 6 3 3

【输出样例】

6

【解题思路】

image

【算法标签】

《洛谷 P1002 过河卒》 #动态规划,dp# #NOIP普及组# #2002#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

// 定义全局变量:
// xb, yb - 目标点B的坐标
// xh, yh - 马的位置坐标
// pand - 标记不能走的点(马的控制点)
// f - 存储到达每个点的路径数
long long xb, yb, xh, yh, pand[30][30] = {0}, f[30][30] = {0};

int main()
{
    // 输入目标点B和马的坐标
    cin >> xb >> yb >> xh >> yh;
  
    // 坐标整体+2,避免处理边界问题(防止数组越界)
    xb += 2; yb += 2;
    xh += 2; yh += 2; 
  
    // 初始化边界条件:最左列和最下行为1(只能直走)
    for (int i = 2; i < 30; i++) {
        f[2][i] = 1;  // 第一列(x=2)
        f[i][2] = 1;  // 第一行(y=2)
    }
  
    // 标记马的控制点(马能走到的8个位置+马本身的位置)
    pand[xh][yh] = 1;       // 马的位置
    pand[xh-2][yh-1] = 1;   // 马走"日"字的8个方向
    pand[xh-1][yh-2] = 1;
    pand[xh+2][yh-1] = 1;
    pand[xh+1][yh-2] = 1;
    pand[xh-2][yh+1] = 1;
    pand[xh-1][yh+2] = 1;
    pand[xh+2][yh+1] = 1;
    pand[xh+1][yh+2] = 1;

    // 动态规划计算路径数
    f[1][2] = 1;  // 初始条件
    for (int i = 2; i <= xb; i++) {
        for (int j = 2; j <= yb; j++) {
            // 如果是马的控制点,则不能走(路径数为0)
            if (pand[i][j] == 1) {
                f[i][j] = 0;
                continue;
            }
            // 状态转移方程:f[i][j] = 从左边来的路径 + 从下边来的路径
            f[i][j] = f[i-1][j] + f[i][j-1];
        }
    }
  
    // 输出到达目标点B的路径总数
    cout << f[xb][yb];
    return 0;
}

【运行结果】

6 6 3 3
6
posted @ 2026-02-17 16:17  团爸讲算法  阅读(14)  评论(0)    收藏  举报