Introduction to C++ Algorithms

This is a problem I encountered during my summer vacation while trying to solve problems on Luogu. After quickly finishing the first problem, A+B, which was as simple as elementary school math, I thought this was the beginning of my dream. However, the second problem, the River Crossing Pawn, gave me a rude awakening. Perhaps I had been away from programming problems for too long, as I was at a loss facing the screen full of errors, and I didn’t think about it further. Recently, I came across a video related to this problem on Bilibili, and I will attempt a different solution again. Below is the source of the problem statement and the problem itself.https://www.luogu.com.cn/problem/P1002Introduction to C++ AlgorithmsIntroduction to C++ AlgorithmsPrevious Approach:Introduction to C++ AlgorithmsIt can be seen that the writing is very messy and hasty. My thought at the time was: isn’t it just a simple enumeration algorithm that can solve it? Since the pawn can only move right or down, I let it move right until it hits a knight’s point or the edge of the board, then move down. If moving down is blocked, I would switch to the next row. Thus, I would traverse down m times from the first row (the coordinates of B are (n,m)), and when encountering a knight’s point, I would try to move right until reaching point B. Finally, I introduced the knight’s point (x,y) and the eight points that the knight can jump to: a[x+2][y+1] and a[x+1][y+2]. At the same time, I also had to consider the knight’s points and the boundaries. Just when I thought this could work, it still resulted in an error.Error Reason: The enumeration data is too large and misses many valid paths. If I enumerate like this, assuming the chessboard is 20*20, then according to the formula$C_{n+m}^{m}$, it can be calculated that there will be 137,846,528,820 paths, which greatly exceeds our memory requirements and computational speed, so this method has already been discarded.How should I correct my previous approach?Introduction to C++ AlgorithmsFirst, we observe the chessboard: Since from A (0,0) to point a, there are only two paths: first right then down, or first down then right. That is to say, the path from A to the point above a has only one way to go right, and the path from A to the left of a has only one way to go down. This means that the number of paths from A to a equals the number of paths from A to (1,0) and from A to (0,1). From this pattern, we can see that the number of paths from A to point d equals the number of paths from A to a plus the number of paths from A to c.Thus, we have derived a recurrence relation:a[i][j]=a[i-1][j]+a[i][j-1]Then we set all accessible cells on the chessboard to 1 and inaccessible cells to 0, meaning that all cells related to the knight’s points are marked as 0.First, implement the code without knight’s points:

#include int main() {    int a[30][30] = {0};    int n, m,x,y;    std::cin >> n >> m;    for (int i = 0; i <= n; i++) {        for (int j = 0; j <= m; j++) {            if (i==0&&j==0){                continue;            }            if (i==0||j==0){                a[i][j] = 1;                           }            else {                a[i][j] = a[i - 1][j] + a[i][j - 1];            }        }    }    std::cout<<a[n][m]; 0;}</a>

Now add the eight knight’s points:Introduction to C++ AlgorithmsThe knight’s points must be within the chessboard and boundary range, meaning that points within the chessboard must be marked as 0.So

if (x+2<=n&&y-1>=0){a[x+2][y-1]=0;}if (x+2<=n&&y+1<=m){a[x+2][y+1]=0;}if (x-2>=0&&y-1>=0){a[x-2][y-1]=0;}if (x-2>=0&&y+1<=m){a[x-2][y+1]=0;}if (x+1<=n&&y+2<=m){a[x+1][y+2]=0;}if (x+1<=n&&y-2>=0){a[x+1][y-2]=0;}if (x-1>=0&&y+2<=m){a[x-1][y+2]=0;}if (x-1>=0&&y-2>=0){a[x-1][y-2]=0;}

Check each of the eight points, integrate the code, and form the complete code:

#include int main() {    int a[30][30] = {0};    int n, m,x,y;    std::cin >> n >> m>>x>>y;    for (int i = 0; i <= n; i++) {        for (int j = 0; j <= m; j++) {            a[i][j] = 1;        }    }    a[x][y] = 0;    if (x+2<=n&&y-1>=0){a[x+2][y-1]=0;}    if (x+2<=n&&y+1<=m){a[x+2][y+1]=0;}    if (x-2>=0&&y-1>=0){a[x-2][y-1]=0;}    if (x-2>=0&&y+1<=m){a[x-2][y+1]=0;}    if (x+1<=n&&y+2<=m){a[x+1][y+2]=0;}    if (x+1<=n&&y-2>=0){a[x+1][y-2]=0;}    if (x-1>=0&&y+2<=m){a[x-1][y+2]=0;}    if (x-1>=0&&y-2>=0){a[x-1][y-2]=0;}       for (int i = 0; i <= n; i++) {        for (int j = 0; j <= m; j++) {                        if (i==0&&j==0){// Skip when at the starting point A                continue;            }            if (a[i][j]==0){// Skip when encountering a knight's point                continue;            }            if (i==0){                a[i][j] = a[i][j - 1];            }            else if (j==0){                a[i][j] = a[i - 1][j];            }                       else {                a[i][j] = a[i - 1][j] + a[i][j - 1];            }        }    }    std::cout<<a[n][m]; 0;}</a>

In lines 30-35, I still do not understand why the number of paths for the first row and the first column equals the number of paths of the previous cell.Reference video:https://www.bilibili.com/video/BV1FC4y1E7BD/?spm_id_from=333.337.search-card.all.click&vd_source=6e24310d9149d3d73e7b80851aae93ee

Leave a Comment