过河卒

写在前面:这篇题解主要是题解区一位大佬的思路,个人感觉还有一点问题,所以写了这么一篇题解。


废话少叙,进入正题。

读题

我们先来分析一下题目,一名卒,开局的时候在 \(A\) 点(坐标 \(0\space0\)),在棋盘坐标上游走 也不知道可不可以瞬移 ,碰到马以及马的控制范围不能走,问有几种方法到达 \(B\) 点.

读完题,感觉好难啊,怎么办,抠细节。

题目中给出了卒的行走方向,只能向下和向右。

这就是一个突破点了,我们可以通过这个简化问题。

已知一个点所有的方法数为从下面和右面来的方法数的和,求公式。

如果我们把这个点命名为 a[i][j] 的话,方法数就是:

\[a_{i,j}\space=\space a_{i-1,j}\space+a_{i,j-1} \]

可是,如果遇到负数下标应该怎么办捏。

负数下标的处理方法

很简单,平移就行。

往右下角平移一个田字格,然后 \(A\) 点由原来的坐标 \((0,0)\) 变成 \((2,2)\)

那在代码中怎么实现呢,只需要把 a[2][2] 标记且 for 循环从 \(2\) 开始就可以了。

标记不能走的地方

题目中说了,只要是马可以控制的地方都不能走,我们可以看着图来分析一下:

假设标记数组为 flag

\(C\) flag[x][y]
\(P1\) flag[x + 2][y + 1]
\(P2\) flag[x + 1][y + 2]
\(P3\) flag[x - 1][y + 2]
\(P4\) flag[x - 2][y + 1]
\(P5\) flag[x - 1][y - 2]
\(P6\) flag[x - 1][y - 2]
\(P7\) flag[x + 1][y - 2]
\(P8\) flag[x + 2][y - 1]

代码实现

#include <iostream>
#include <cstdio>
using namespace std;
long long a[50][50],flag[50][50];
int main() {
	int n,m,x,y;
	cin >> n >> m >> x >> y;
	n += 2,m += 2,x += 2,y += 2; // 往下平移一个田字格 
	// 标记不能走的地方 
	flag[x][y] = 1;
	flag[x + 2][y + 1] = 1;
	flag[x + 1][y + 2] = 1;
	flag[x - 1][y + 2] = 1;
	flag[x - 2][y + 1] = 1;
	flag[x - 2][y - 1] = 1;
	flag[x - 1][y - 2] = 1;
	flag[x + 1][y - 2] = 1;
	flag[x + 2][y - 1] = 1;
	// 平移 
	a[2][2] = 1;
	flag[2][2] = 1;
	// 循环解决 
	for(int i = 2;i <= n;i++) {
		for(int j = 2; j <= m;j++) { 
			if(!flag[i][j]) // 如果可以走 
			   // 递推关系式 
			   a[i][j] = a[i - 1][j] + a[i][j - 1]; // 下面和右面 
		}
	}
	cout << a[n][m];
	return 0;
} 

完结撒花~

posted @ 2023-09-24 09:58  卡布叻-空白  阅读(35)  评论(0)    收藏  举报