跳跃版图 java 大整数 记忆化搜索 dp

题目描述

有一个 n×n 的格子,每个格子中有一个非负整数。你的目标是从左上角跳到右下角,每步只能向右或向下跳。格子中的数代表从该格开始跳跃的前进步数,如果某次跳跃会跃出格子 界限则该跳跃是禁止的。注意 0 是一个绝对终点,因为从这里无法再移动。


你的任务是统计有多少种合法路径。上图 1 中共有 3 种路径,分别表示在图 2 中。

输入
第一行,一个整数 n(3 ≤ n ≤ 100)。

接下来 n 行 n 列,表示格子中的数,所有数的范围在[0,9]中,两个数之间用一个空格隔开。

输出

第一行,从左上角到右下角的合法路径数目。

样例输入
4
2 3 3 1
1 2 1 3
1 2 3 1
3 1 1 0

样例输出
3

思路

裸记忆化搜索,从(1,1)开始朝两个方向深度优先搜索,搜索完一个节点之后,然后用一个DP数组存储即可,但是得注意对终点(mp[i][j] == 0)的特判退出情况,否则会爆栈。

代码

import java.util.Scanner;
import java.math.BigInteger;
 
public class Main {
    static BigInteger dp[][]=new BigInteger[110][110];
    static int[][] mp=new int[110][110];
    static int dir[][]=new int[2][2];
    static int n;
     
    static BigInteger dfs(int x,int y){
        if(dp[x][y].compareTo(BigInteger.ZERO)>0) return dp[x][y];
        for(int i=0;i<2;i++){
            int xx=dir[i][0]*mp[x][y]+x;
            int yy=dir[i][1]*mp[x][y]+y;
            if(x==xx&&y==yy) return BigInteger.ZERO;
            else if(xx==n&&yy==n){
                dp[x][y]=dp[x][y].add(BigInteger.ONE);
                continue;
            }
            if(xx>=1&&xx<=n&&yy>=1&&yy<=n)
                dp[x][y]=dp[x][y].add(dfs(xx,yy));
        }
        return dp[x][y];
    }
     
    public static void main(String[] args) {
        Scanner scan =new Scanner (System.in);
        while(scan.hasNext()) {
            n=scan.nextInt();
            for(int i=1;i<=n;i++) {
                for (int j=1; j<=n;j++) {
                    mp[i][j]=scan.nextInt();
                }
            }
            dir[0][1]=dir[1][0]=1;
            dir[0][0]=dir[1][1]=0;
            for(int i=1;i<=n;i++) {
                for(int j=1;j<=n;j++) {
                    dp[i][j]=BigInteger.ZERO;
                }
            }
            dfs(1,1);
            System.out.println(dp[1][1]);
        }
         
    }
}
学如逆水行舟,不进则退
发布了591 篇原创文章 · 获赞 1743 · 访问量 29万+

猜你喜欢

转载自blog.csdn.net/weixin_42429718/article/details/105032485
今日推荐