洛谷 P1002 过河卒 Java实现(解法优化版本)

题目描述

洛谷 P1002 过河卒 Java实现(解法优化版本)_第1张图片

算法思想

当前点到目标点的路径数量就是:右边的点到目标点的路径数量+下面的点到目标点的路径数量,依次类推,直到目标点。

由于我们是知道目标点位置的,所以直接从目标点开始,依次计算节点到目标节点的路径数量,赋值完成后起点(0,0)的值就是题目的解。

以下为核心代码:

public static void getPathPro(long[][] map,int aim_x,int aim_y){


        for(int i=aim_x;i>=0;i--){

            for(int j=aim_y;j>=0;j--){

                if(map[i][j]>=0){

                    if(map[i+1][j]>=0){
                        map[i][j]+=map[i+1][j];
                    }
                    if(map[i][j+1]>=0){
                        map[i][j]+=map[i][j+1];
                    }
                }
            }

        }
    }

第一步:初始化数组;

为了运行操作的一致性,在初始化数组时,若目标点为(n,m)则初始化的数组为long[n+1][m+1](由于最右边节的一列节点没有右节点,最下面一行的节点没有下面的节点)。

Scanner scanner=new Scanner(System.in);
        
        //目标点位置
        int aim_x=scanner.nextInt();
        int aim_y=scanner.nextInt();
        
        //马的位置
        int horse_x=scanner.nextInt();
        int horse_y=scanner.nextInt();

        //用于描述棋盘的数组
        long[][] map=new long[aim_x+2][aim_y+2];

第二步:为马的位置及马的控制点的位置赋值(-1),为目标点及目标点下面的点(或者右边的点)赋值(1);

       int[]step=new int[]{1,2,-1,-2};
        int[] xDirection=new int[4];
        int[] yDirection=new int[4];

        //存储马的向右及向下所能到达的单维度的值
        for(int i=0;i<=3;i++){

            xDirection[i]=horse_x+step[i];
            yDirection[i]=horse_y+step[i];

        }

        //为马的控制点赋值(-1)
        for(int i=0;i<=3;i++){
            for(int j=0;j<=3;j++) {

                if(xDirection[i]>=0&&yDirection[j]>=0){

                    //if条件用于防止出现右方向和下方向同时加正负1和正负2的情况,从而正确得到马的控制点
                    if(i%2!=j%2){

                        if(xDirection[i]<=aim_x&&yDirection[j]<=aim_y){

                        }
                        map[xDirection[i]][yDirection[j]]=-1;
                    }
                }

            }
        }

        //为马所在点赋值(-1)
        map[horse_x][horse_y]=-1;
        //为目标点下方的点(或者右方的点也可)赋值(1)
        map[aim_x+1][aim_y]=1;

第三步:调用getPathPro()从目标点开始,为当前节点赋值(右边点的值加上下面点的值),最后输出点(0,0)的值即为题解。


		getPathPro(map,aim_x,aim_y);

        System.out.println(map[0][0]);


public static void getPathPro(long[][] map,int aim_x,int aim_y){


        for(int i=aim_x;i>=0;i--){

            for(int j=aim_y;j>=0;j--){

                if(map[i][j]>=0){

                    if(map[i+1][j]>=0){
                        map[i][j]+=map[i+1][j];
                    }
                    if(map[i][j+1]>=0){
                        map[i][j]+=map[i][j+1];
                    }
                }
            }

        }


    }

完整代码


import java.util.Scanner;

public class P1002_SoliderCrossRiver {

    public static void main(String[] args){

        Scanner scanner=new Scanner(System.in);

        //目标点位置
        int aim_x=scanner.nextInt();
        int aim_y=scanner.nextInt();

        //马的位置
        int horse_x=scanner.nextInt();
        int horse_y=scanner.nextInt();

        //用于描述棋盘的数组
        long[][] map=new long[aim_x+2][aim_y+2];

        int[]step=new int[]{1,2,-1,-2};
        int[] xDirection=new int[4];
        int[] yDirection=new int[4];

        //存储马的向右及向下所能到达的单维度的值
        for(int i=0;i<=3;i++){

            xDirection[i]=horse_x+step[i];
            yDirection[i]=horse_y+step[i];

        }

        //为马的控制点赋值(-1)
        for(int i=0;i<=3;i++){
            for(int j=0;j<=3;j++) {

                if(xDirection[i]>=0&&yDirection[j]>=0){

                    //if条件用于防止出现右方向和下方向同时加正负1和正负2的情况,从而正确得到马的控制点
                    if(i%2!=j%2){

                        if(xDirection[i]<=aim_x&&yDirection[j]<=aim_y){

                        }
                        map[xDirection[i]][yDirection[j]]=-1;
                    }
                }

            }
        }

        //为马所在点赋值(-1)
        map[horse_x][horse_y]=-1;
        //为目标点下方的点(或者右方的点)赋值(1)
        map[aim_x+1][aim_y]=1;


        getPathPro(map,aim_x,aim_y);

        System.out.println(map[0][0]);



    }


    public static void getPathPro(long[][] map,int aim_x,int aim_y){


        for(int i=aim_x;i>=0;i--){

            for(int j=aim_y;j>=0;j--){

                if(map[i][j]>=0){

                    if(map[i+1][j]>=0){
                        map[i][j]+=map[i+1][j];
                    }
                    if(map[i][j+1]>=0){
                        map[i][j]+=map[i][j+1];
                    }
                }
            }

        }


    }


}

运行示例(数组内容仅用于展示,答题只需输出路径数量)

洛谷 P1002 过河卒 Java实现(解法优化版本)_第2张图片

个人总结

在前日第一次做题时,使用的是简单暴力的递归方式,依次寻找点到目标点的路径,若目标点近时,还能到达答题要求,但是目标点远点则需要运行很久才能得到答案,且前日使用int类型回到的路径数量过大,溢出的情况,本次改用长整型long。这两天的独立思考,代码性能及解答都符合解题要求,也算是小小的进步。

你可能感兴趣的:(洛谷 P1002 过河卒 Java实现(解法优化版本))