【C++】 递推----过河卒问题

递推----过河卒问题

首先,让我们先来了解一下有关二维数组的语法
1.如何定义二维数组
类型 数组名[长度1][长度2];

esp.:int a[3][3];

2.赋值:
数组名[长度1][长度2]=值
或者在定义的时候进行赋值:
数组名[长度1][长度2]={{值,值},{值,值}…};

esp::int a[2][2]={{1,2},{3,4}};或: a[3][3]=5;

3.输出:
以整形数组为例

printf("%d",a[3][3]);

现在在让我们来看一个经典的问题:

*A点有一个过河卒 需要走到目标B点,它只能向下或者向右移动
在棋盘中的任意一个点上有对方的马,记为C点,马所在的点和所有跳跃一步可达的点称为对方马的控制点,小卒不能通过马的控制点
现给定A点位置(0,0),B(m,n)(m,n<=20),C(x,y)且C不与A,B重叠
计算出小卒从A顺利到达B的路径条数
输入:B点坐标(n,m)以及对方马C的坐标(x,y) (马的坐标一定在棋盘范围内,但可能落在边界上)
输出: 小卒从A点到B点的路径条数
输入样例:6 6 3 2
输出样例:17

*首先想到,在遇到横向和纵向两个维度的数据时,应当使用二维数组
从A点到B点的路径受两个因素影响:
1.小卒本身的行走规则
2.马及其控制点的影响
在这里插入图片描述

先不考虑马的存在,只分析小卒的行走路径
用数字表示出,当B在该位置的时候,A到B的路径条数,如下图所示:
在这里插入图片描述

会发现,当前点的路径条数=左边路径条数+上边路径条数
这里有一个特殊情况:
下标为0的行没有上边的路径,故等于其左边的值
下标为0的列没有左边的路径,故等于上边的值

因此,可以创建一个二维数组a[21][21](数组空间要比20大一点),来存储行和列
注意,前边已经说过,不要忘记初始化数组
当行为0,纵为0的时候,只有一条路径(排除B与A点重合的情况)

再考虑有马存在的时候
马及其控制点的位置,小卒不能通过,故需要标记马及其控制点的位置
具体操作方式可以为:

将A,B之前的格全部初始化为1,将马及其控制点标记为0,通过判断是1还是0来判断是否为马的控制点,从而判断马是否挡路

还有一个条件需要判断:马及其控制点是否在A与B中间,若不在,则以上所有不需要去考虑(因为小卒只能向右和下走)
分析完毕,下面是代码

#include <iostream>
using namespace std;
int main(){
	int a[21][21]={0};
	int m,n,x,y;
	cin>>m>>n>>x>>y;
	for(int i=0;i<=m;i++){
		for(int k=0;k<=n;k++){
			a[i][k]=1;
		}
	}
	//如果在AB范围内,标记为0
	if(x-1>=0&&y-2>=0) a[x-1][y-2]=0;//P1
	if(x+1<=m&&y-2>=0) a[x+1][y-2]=0;//P2
	if(x+2<=m&&y-1>=0) a[x+2][y-1]=0;//P3
	if(x+2<=m&&y+1<=n) a[x+2][y+1]=0;//P4
	if(x+1<=m&&y+2<=n) a[x+1][y+2]=0;//P5
	if(x-1>=0&&y+2<=n) a[x-1][y+2]=0;//P6
	if(x-2>=0&&y+1<=n) a[x-2][y+1]=0;//P7
	if(x-2>=0&&y-1>=0) a[x-2][y-1]=0;//P8
	//还要考虑马所在的点
	a[x][y]=0;
	for(int i=0;i<=m;i++){
		for(int k=0;k<=n;k++){
			//A与B重合时
			if(i==0&&k==0) continue;
			//避开马及其控制点
			if(a[i][k]==0) continue; 
			//在行为0,和纵为0的地方  
			if(i==0){
				a[i][k]=a[i][k-1];
			}else if(k==0){
				a[i][k]=a[i-1][k];
			}else a[i][k]=a[i][k-1]+a[i-1][k];
		}
	}
	cout<<a[m][n];
	return 0;
}

END…

ps:国庆假期第三天了

“我想,放假的意义就在于:一个说不起就不起的早晨、一个说不睡就不睡的深夜和一个说不出门就不出门的白天;又或者是满怀期待地去想见的人,去奔赴山海,去做梦,去闲着。”

愿大家都能享受自己的假期~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值