过河卒

过河卒

本题链接p1002 过河卒

题目描述

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

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

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

输入格式

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

输出格式

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

说明/提示

对于100%的数据, $ 1≤n,m≤20 $ ,$ 0≤ $ 马的坐标 $ ≤20 $。

求解

我看到这题时,我就想到用递推来做这题

1. 根据题意并根据样例,第一步可以写出下列 (简单的) 表格:

[0] [1] [2] [3] [4] [5] [6]
[0] 0 1 1 1 1 1 1
[1] 1 2 3 4 5 6 7
[2] 1 3 6 10 15 21 28
[3] 1 4 10 20 35 56 84
[4] 1 5 15 35 70 135 219
[5] 1 6 21 56 126 261 370
[6] 1 7 28 84 210 471 841

(显而易见),这里可以利用加法原理,写出递推式

\[f[i][j]=f[i-1][j]+f[i][j-1];(start:f[0][0]=1) \]

2. 第二步再加上马的影响

[0] [1] [2] [3] [4] [5] [6]
[0] 1 1 1 1 1 1 1
[1] 1 2 0 1 0 1 2
[2] 1 0 0 1 1 0 2
[3] 1 1 1 0 1 1 3
[4] 1 0 1 1 2 0 3
[5] 1 1 0 1 0 0 3
[6] 1 2 2 3 3 3 6

根据这个表格,我们可以想到先把马的控制点,也就是马能到达的地方(包括他本身的这个点,做一个预处理,之后递推的时候,如果到达马的控制点,直接跳过,继续下一个点。

基本思路就是这样,但是在测评中发现了第三个点:只有long long类型才能AC。

代码如下:

#include <iostream>   
#include <cstdio>
using namespace std;
int n,m,x,y;
long long map[42][42]={{1}};  \\递推开始式为f[0][0] = 1;
bool horse[42][42];
int hx[9]={0,1,1,2,2,-1,-1,-2,-2},  \\马的位移
	hy[9]={0,2,-2,1,-1,2,-2,1,-1};
int main ()
	{
		cin>>n>>m>>x>>y;
		for (int i=0;i<=8;i++)
			{
				int xx=x+hx[i],yy=y+hy[i];
				if (xx>n||xx<0||yy>m||yy<0)
					continue;
				horse[xx][yy]=1;
			}
		int l=0,k=0;
		while (!horse[0][++k]&&k<=m)
			map[0][k]=1;
		while (!horse[++l][0]&&l<=n)
			map[l][0]=1;
		for (int i=1;i<=n;i++)
			for (int j=1;j<=m;j++)
				if (!horse[i][j])
					map[i][j]=map[i-1][j]+map[i][j-1];   \\递推式
		cout<<map[n][m]<<endl;
		return 0;
	}
posted @ 2021-02-18 19:41  在那遥远的悠穹下  阅读(204)  评论(0编辑  收藏  举报