蓝桥杯递推--马踏过河卒

题目:

在这里插入图片描述
A点有一个过河卒,需要走到目标B点。卒行走规则:可以向下、或者向右。同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点。例如上图C点上的马可以控制9个点(图中的 P1,P2⋯P8和C)。卒不能通过对方马的控制点。

棋盘用坐标表示,A点(0,0)、B点(n,m)、C 点(cx​,cy​)(0<cx<n≤20,0<cy<m≤20)。现在要求你计算出过河卒从A 点能够到达B 点的路径的条数。注:象棋中马走“日”。

Input
输入4个整数,n,m,cx​,cy​,分别表示C 点的横坐标和C 点的纵坐标。

Output
输出一个整数,代表从A 点走到B 点的所有路径数。

Sample Input 1

5 5 2 4
Sample Output 1

14

思路:
理解了递推的核心思想其实这题并不难,就是先推倒他的关系式,都过关系式进行类似有dp的循环操作即可,本题中关系式不难得出,f(i,j) = f(i-1,j) + f(i,j-1)(因为只能向下或者向右移动),设置初始值为f(0,0) = 1,不过这题有一个陷阱就是dp数组要设置为long long 类型的,不然会超出范围

说到这里,我就想把我理解的递推的思想在总结一下,就以这道题为例,思想就是当你可以反过来想问题,倒着想,比如说向下走或者向右走,可以想像成当前的点是由他的上面的那个点或者是他的左边的那个点移动过来的,这样就不难推出递推的公式了,画一个图:


在这里插入图片描述

上代码:

#include"bits/stdc++.h"
using namespace std;
int n, m, cx, cy, sum = 0;
int vis[25][25];
long long dp[25][25];   // 一定要注意 这里有可能超范围
int main(){
	cin >> n >> m >> cx >> cy;
	
	memset(dp,0,sizeof(dp));
	memset(vis,0,sizeof(vis));

	if(cx-1 >= 0 && cy+2 <= m){
		vis[cx-1][cy+2] = 1; 
	}
	if(cx+1 <= n && cy+2 <= m){
		vis[cx+1][cy+2] = 1;
	}
	if(cx+2 <= n && cy+1 <= m){
		vis[cx+2][cy+1] = 1;
	}
	if(cx+2 <= n && cy-1 >= 0){
		vis[cx+2][cy-1] = 1;
	}
	if(cx+1 <= m && cy-2 >= 0){
		vis[cx+1][cy-2] = 1;
	}
	if(cx-1 >= 0 && cy-2 >= 0){
		vis[cx-1][cy-2] = 1;
	}
	if(cx-2 >= 0 && cy-1 >= 0){
		vis[cx-2][cy-1] = 1;
	}
	if(cx-2 >= 0 && cy+1 <= m){
		vis[cx-2][cy+1] = 1;
	}
	vis[cx][cy] = 1;

	dp[0][0] = 1;
	for(int i = 0;i <= n;i ++){
		for(int j = 0;j <= m;j ++){
			if(i){
				if(vis[i][j]) dp[i][j] = 0;
				else dp[i][j] += dp[i-1][j]; // i对应i-1  !!!  要理解为啥 
			} 
			if(j){
				if(vis[i][j]) dp[i][j] = 0;
				else dp[i][j] += dp[i][j-1]; // j对应j-1  !!!  if语句中代表向下走,改变的是列,所以这一步一定是要加上上面的那个位置对应的数值 
			}  
		}
	}
	
	
	cout << dp[n][m];
	return 0;
}

爱父母,爱亲人,看淡人生,不忘初心

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rabbit Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值