题目链接:https://www.luogu.org/problemnew/show/P1002
题目还算良心,提醒了结果可能很大,确实爆了int范围,
这是一开始写的版本,用递归做的,先给地图做标记,每到一个点,这个点可以走的话,选择向下走还是向右走,但是会超时。
#include <iostream> using namespace std; int sign[23][23]; int M, N; int res = 0; void move(int i, int j) { if (i == N && j == M) { res++; return; } if (i < N&&sign[i + 1][j] != 1) move(i + 1, j); if (j < M&&sign[i][j + 1] != 1) move(i, j + 1); } void make_mark(int x, int y) { sign[x - 1][y - 2] = 1; sign[x - 1][y + 2] = 1; sign[x + 1][y + 2] = 1; sign[x + 1][y - 2] = 1; sign[x + 2][y - 1] = 1; sign[x + 2][y + 1] = 1; sign[x - 2][y - 1] = 1; sign[x - 2][y + 1] = 1; sign[x][y] = 1; } int main() { int x, y; cin >> N >> M >> x >> y; make_mark(x, y); move(0, 0); cout << res << endl; return 0; }
然后改成了动态规划,手画个表就明白了,这是不考虑“马”的因素,到每个点的步数:
第一行,第一列可确定,其余的等于自己的左+上。
没做越界处理的原因:随手记——神奇的现象,二维数组
#include <iostream> using namespace std; int sign[23][23]; long long dp[21][21]; int M, N; void make_mark(int x,int y) { sign[x - 1][y - 2] = 1; sign[x - 1][y + 2] = 1; sign[x + 1][y + 2] = 1; sign[x + 1][y - 2] = 1; sign[x + 2][y - 1] = 1; sign[x + 2][y + 1] = 1; sign[x - 2][y - 1] = 1; sign[x - 2][y + 1] = 1; sign[x][y] = 1; } int main() { int x, y; cin >> N >> M >> x >> y; make_mark(x, y); int flag = 1; for (int i = 0; i <= N; i++) { if (sign[i][0])flag = 0; dp[i][0] = flag; } flag = 1; for (int i = 0; i <= M; i++) { if (sign[0][i])flag = 0; dp[0][i] = flag; } for (int i = 1; i <= N; i++) { for (int j = 1; j <= M; j++) { if (sign[i][j] == 1) dp[i][j] = 0; else dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; } } cout << dp[N][M] << endl; return 0; }