随手练——洛谷-P1002 过河卒(动态规划入门)

题目链接: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;
}
View Code

然后改成了动态规划,手画个表就明白了,这是不考虑“马”的因素,到每个点的步数:

然后代码:

#include <iostream>
using namespace std;

int maze[25][25];
long long dp[25][25];
int dis[][2] = { {-1,-2},{-1,2},{1,2},{1,-2},{2,-1},{2,1},{-2,-1},{-2,1} };
int M, N, x, y;

int main() {
    cin >> N >> M >> x >> y;
    N++; M++; x++; y++;//起点用(1,1)做,后面不会出现下标越界情况,所有点都+1
    maze[x][y] = 1;
    for (int i = 0; i < 8; i++) {
        //标记马的位置,全局数组多开了几个,可以不做越界判断
        maze[x + dis[i][0]][y + dis[i][1]] = 1;
    }
    dp[0][1] = 1;//使得在循环内能够正常初始化 起点 (1,1)
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (maze[i][j])continue;
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        }
    }
    cout << dp[N][M] << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/czc1999/p/10361307.html