洛谷 P1002 [NOIP2002 普及组] 过河卒

题目链接:

https://www.luogu.com.cn/problem/P1002

题目:

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

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

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

输入格式:

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

输出格式:

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

例如:输入:

6 6 3 3

           输出:

6

思路:

一个标准入门的dp问题。

该题使用标数法的思想解决。

首先我们不妨让起点(0,0)改变为(1,1)并且假设马控制点都不存在,以便后续操作。

由于卒位于(1,1)点且只能向下或向右,所以假设在目标B点(n+1,m+1)有z种路径可以到达,到达点上方(n,m+1)的路径有x种,到达点左边点(n+1,m)的路径有y种,则有等式成立z=x+y。

但是存在一个问题,我们不知道到达每个点的上方点的路径数和左边点的路径数,所以我们设置一个足够大的二维整形数组map作为地图使用并且全部初始化为0,设置到达起点(1,1)的路径数为1,让循环按行去遍历每一个点,计算出起点到达该点的路径总数,直到终点。

接下来我们对马控制点进行出列,假设马的坐标为(a,b),使用一个和地图map大小相同的布尔数组ma并且将该数组的内容全部初始化为0(即为false\假),编写一个方向数组让其元素加上马的坐标点后是马控制点并且让ma中该坐标点变为真\true(或者你用马的坐标一个一个加上方向,然后改为真)。

当我们循环遍历到该马控制点时,我们使用直接使用continue让到达该路径总数为0。

最后我们输出目标点(n+1,m+1)的可到达路径数即可。

AC代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

int ax, ay, mx, my;
bool ma[25][25] = { 0 };
long long step[25][25] = { 0 };
int dir[9][2] = {
	{0,0},{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}
};

int main() {

	scanf("%d%d%d%d", &ax, &ay, &mx, &my);
	for (int i = 0; i < 9; i++) {
		ma[1 + mx + dir[i][0]][1 + my + dir[i][1]] = 1;
	}
	step[1][1] = 1;
	for (int i = 1; i <= (ax + 1); i++) {
		for (int j = 1; j <= (ay + 1); j++) {
			if (ma[i][j]) {
				continue;
			}
			step[i][j] += (step[i - 1][j] + step[i][j - 1]);
		}
	}
	printf("%lld", step[ax + 1][ay + 1]);

	return 0;
}

如果我的文章对你有所帮助,不妨给我个关注何点赞吧.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值