过河卒
写在前面:这篇题解主要是题解区一位大佬的思路,个人感觉还有一点问题,所以写了这么一篇题解。
废话少叙,进入正题。
读题
我们先来分析一下题目,一名卒,开局的时候在 \(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;
}
完结撒花~

浙公网安备 33010602011771号