題目描述
有一個 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]);
}
}
}
學如逆水行舟,不進則退