【1314】【例3.6】过河卒(Noip2002)

本文介绍了如何解决一个棋盘上的过河卒问题,即卒从A点到B点需要避开马的控制点。通过分析,得出可以使用逐列或逐行递推的方法计算路径数量,避免了回溯或搜索导致的时间复杂度过高。文章提供了算法分析、递推公式以及边界条件,并指出在最大规模下需考虑高精度计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【问题描述】
       棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B。现在要求你计算出卒从A点能够到达B点的路径的条数。
在这里插入图片描述 【输入】
       给出n、m和C点的坐标。
【输出】
       从A点能够到达B点的路径的条数。
【输入样例】
       8 6 0 4
【输出样例】
       1617
【算法分析】
       跳马是一道老的不能再老的题目,我想每位编程初学者都学过,可能是在学回溯或搜索等算法的时候,很多书上也有类似的题目,一些比赛中也出现过这一问题的变形(如Noip1997初中组的第三题)。有些同学一看到这条题目就去搜索,即使你编程调试全通过了,运行时你也会发现:当n、m=15就会超时。
       其实,本题稍加分析就能发现,要到达棋盘上的一个点,只能从左边过来(我们称之为左点)或是从上面过来(我们称之为上点),所以根据加法原理,到达某一点的路径数目,就等于到达其相邻的上点和左点的路径数目之和,因此我们可以使用逐列(或逐行)递推的方式来求出从起点到终点的路径数目。障碍点(马的控制点)也完全适用,只要将到达该点的路径数目设置为0即可。
用dp[i][j]表示到达点(i,j)的路径数目,g[i][j]表示点(i,j)有无障碍,g[i][j]=0表示无障碍,g[i][j]=1表示有障碍。则,递推关系式如下:
       dp[i][j] = dp[i-1][j] + dp[i][j-1]           // i>0且j>0且g[i][j]=0
       递推边界有4个:
       dp[i][j] = 0                                       // g[i][j] = 1
       dp[i][0] = dp[i-1][0]                          // i>0且g[i][0] = 0
       dp[0][j] = dp[0][j-1]                          // j>0且g[0][j] = 0
       dp[0][0] = 1
       考虑到最大情况下:n=20,m=20,路径条数可能会超过2^31-1,所以要用高精度。
【参考程序】

#include <iostream> 
#include <cstdio>
#include <cstring>
using namespace std;

#define maxn 50

int arr[maxn][maxn];						// 记录马可以到达的地方 
long long int dp[maxn][maxn];				// dp[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值