列表

详情


NC369. [NOIP2002 普及组] 过河卒

描述

棋盘上 A点有一个过河卒,需要走到目标 B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,A 点 (0, 0)、B点(n,m),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 A点能够到达 B点的路径的条数,假设马的位置(x,y)是固定不动的,并不是卒走一步马走一步。
注:马一次跳跃到达的点(x1,y1)和马原坐标(x,y)的关系是


数据范围: ,马的坐标

示例1

输入:

6,6,3,3

输出:

6

示例2

输入:

5,4,2,3

输出:

3

示例3

输入:

2,5,3,5

输出:

1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 3ms, 内存消耗: 392KB, 提交时间: 2022-05-22

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 棋盘行数
     * @param m int整型 棋盘列数
     * @param x int整型 马的横坐标
     * @param y int整型 马的纵坐标
     * @return int整型
     */
    /*void CrossRiverCore(int n, int m, int x, int y, int inx, int iny,int& ret) {
        if (inx > n || iny > m) return;
        if (inx == x && iny == y || inx == x + 2 && iny == y + 1 || inx == x + 2 && iny == y - 1 ||
            inx == x - 2 && iny == y - 1 || inx == x - 2 && iny == y + 1) return;
        if (inx == x - 1 && iny == y - 2 || inx == x - 1 && iny == y + 2 || 
            inx == x + 1 && iny == y + 2  || inx == x + 1 && iny == y - 2)
            return;
        if (inx == n && iny == m) ret++;
        CrossRiverCore(n, m, x, y, inx + 1, iny, ret);
        CrossRiverCore(n, m, x, y, inx, iny + 1, ret);
}

    int crossRiver(int n, int m, int x, int y) {
        // write code here
         int ret = 0;
         CrossRiverCore(n, m, x, y, 0, 0, ret);
         return ret;
    }*/
    
    int crossRiver(int n, int m, int x, int y) {
    // write code here
        int** res = new int* [2];
        for (int i = 0; i < 2; i++) res[i] = new int[m + 1];
        /*int res[7][7] = { 0 };*/
        int oldVal = 0, newVal = 1;
        for (int i = 0; i <= n; i++) {
            oldVal = newVal;
            newVal = 1 - oldVal;
            for (int j = 0; j <= m; j++) {
                bool state1 = 0;
                if (i == x && j == y || i == x + 2 && j == y + 1 || i == x + 2 && j == y - 1 ||
                    i == x - 2 && j == y - 1 || i == x - 2 && j == y + 1 ||
                    i == x - 1 && j == y - 2 || i == x - 1 && j == y + 2 ||
                    i == x + 1 && j == y + 2 || i == x + 1 && j == y - 2)
                    state1 = true;
                if (i == 0 || j == 0) {
                    if (i == 0 && j > 0) {
                        if (state1 == true || res[newVal][j - 1] == 0) res[newVal][j] = 0;
                        else res[newVal][j] = 1;
                    }
                    if (j == 0 && i > 0) {
                        if (state1 == true || res[oldVal][j] == 0) res[newVal][j] = 0;
                        else res[newVal][j] = 1;
                    }
                    if(i==0&&j==0) res[newVal][j]=1;
                    continue;
                }
                res[newVal][j] = res[oldVal][j] + res[newVal][j - 1];
                if (state1 == true) res[newVal][j] = 0;
            }
        }
        int ret = res[newVal][m];
        for (int i = 0; i < 2; i++) delete[] res[i];
        delete[] res;
        return ret;
}

};

C++ 解法, 执行用时: 3ms, 内存消耗: 408KB, 提交时间: 2022-06-19

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 棋盘行数
     * @param m int整型 棋盘列数
     * @param x int整型 马的横坐标
     * @param y int整型 马的纵坐标
     * @return int整型
     */
    int crossRiver(int n, int m, int x, int y) {
        // write code here
//         
//         vector<pair<int, int>> visit;
//         recursion(visit, n, m, x, y, 0, 0);
        vector<vector<int>>dp(n + 1, vector<int>(m + 1, 0));
        dp[0][0] = 1;
        
        for(int i = 0; i <= n; i ++){
            for(int j = 0; j <= m; j ++){
                if( (abs(i - x) + abs (j - y)) == 3 && i != x && j != y){
                    dp[i][j] = 0;
                }else if(i == x && j == y){
                    dp[i][j] = 0;
                }else if(i > 0 && j == 0 ){
                    dp[i][j] = dp[i - 1][j];
                }else if( j > 0 && i == 0){
                    dp[i][j] = dp[i][j - 1];
                }else if (i > 0 && j > 0){
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[n][m];
        
    }
    
//     void recursion(vector<pair<int, int>> visit, int n, int m, int x, int y, int i, int j){
//         if(i > n || j > m || ((abs(i - x) + abs (j - y)) == 3 && i != x && j != y)){
//             visit.pop_back();
//             return;
//         }
// //         visit[i][j] = 1;
//         visit.push_back({i, j});
// //         visit.insert({i, j});
//         if( i == n && j == m) {
// //             res ++;
//             path.insert(visit);
//         }
//         recursion(visit, n, m, x, y, i + 1, j);
        
//         recursion(visit, n, m, x, y, i, j + 1);
//     }
    
    
};

C++ 解法, 执行用时: 3ms, 内存消耗: 444KB, 提交时间: 2022-08-02

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 棋盘行数
     * @param m int整型 棋盘列数
     * @param x int整型 马的横坐标
     * @param y int整型 马的纵坐标
     * @return int整型
     */
    int _x=0;
    int _y=0;
    int _n=0;
    int _m=0;
    vector<vector<int>>dp;
    int crossRiver(int n, int m, int x, int y) {
        // write code here
        _n=n;
        _m=m;
        _x=x;
        _y=y;
        dp.resize(n+1,vector<int>(m+1,-1));
        return process(0,0);
    }
    int process(int row,int col)
    {
        if(row>_n||col>_m)
        {
            return 0;
        }
        if(check(row,col))
        {
            return 0;
        }
        if(row==_n&&col==_m)
        {
            dp[row][col]=1;
            return 1;
        }
        if(dp[row][col]!=-1)
        {
            return dp[row][col];
        }
        int ans=0;
        ans+=process(row+1,col);
        ans+=process(row,col+1);
        dp[row][col]=ans;
        return ans;
    }
    bool check(int row,int col)
    {
        if(abs(_x-row)+abs(_y-col)==3&&_x!=row&&_y!=col)
        {
            return true;
        }
        else if(row==_x&&col==_y)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

C++ 解法, 执行用时: 4ms, 内存消耗: 404KB, 提交时间: 2022-08-02

class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param n int整型 棋盘行数
     * @param m int整型 棋盘列数
     * @param x int整型 马的横坐标
     * @param y int整型 马的纵坐标
     * @return int整型
     */
    vector<vector<int>>dp;
    int crossRiver(int n, int m, int x, int y) {
        // write code here
        dp.resize(n + 1, vector<int>(m + 1,0));
        return process(n, m, x, y, 0, 0);
    }
    int process(int n, int m, int x, int y, int row, int col) {
        if (row > n || col > m) {
            return 0;
        }
        if (Check(row, col, x, y)) {

            return 0;
        }
  
        if (row == n && col == m) {
           // dp[row][col]=1;
            return 1;
        }
        //注意不能填-1因为有些点再马点中
        if(dp[row][col]!=0){
            cout<<row<<":"<<col<<endl;
            return dp[row][col];
        }

        int p1 = process(n, m, x, y, row + 1, col);
        int p2 = process(n, m, x, y, row, col + 1);
        int ans = p1 + p2;
        dp[row][col] = ans;
        return ans;
    }
    bool Check(int i, int j, int x, int y) {
        //检查是否是马点
        return (abs(x - i) + abs(y - j) == 3 && i != x && j != y) || (i == x && y == j);
    }


};

C++ 解法, 执行用时: 4ms, 内存消耗: 424KB, 提交时间: 2022-08-06

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 棋盘行数
     * @param m int整型 棋盘列数
     * @param x int整型 马的横坐标
     * @param y int整型 马的纵坐标
     * @return int整型
     */
    int crossRiver(int n, int m, int x, int y) {
        // write code here
        vector<vector<int>> dp(n+1,vector<int>(m+1,0));
        dp[0][0]=1;
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=m;j++)
            {
                if((abs(i-x)+abs(j-y))==3&&i!=x&&j!=y)
                    dp[i][j]=0;
                else if(i==x&&j==y)
                    dp[i][j]=0;
                else if(i>0&&j==0)
                {
                    dp[i][j]=dp[i-1][j];
                }else if(j>0&&i==0)
                    dp[i][j]=dp[i][j-1];
                else if(i>0&&j>0)
                {
                    dp[i][j]=dp[i-1][j]+dp[i][j-1];
                }
            }
        }
        return dp[n][m];
    }
};

上一题