576.Β Out of Boundary Paths

  • 크기가 m x n 인 곡간이 μ‘΄μž¬ν•  λ•Œ νŠΉμ • μœ„μΉ˜ (startRow, startColumn)μ—μ„œ μ΅œλŒ€ maxMove 회 만큼 μ›€μ§μ˜€μ„ λ•Œ ν•΄λ‹Ή κ³΅κ°„μ—μ„œ λ²—μ–΄λ‚  수 μžˆλŠ” 경우의 수λ₯Ό κ΅¬ν•˜λŠ” 문제.
  • μš°μ„  μ΅œλŒ€ 움직일 수 μžˆλŠ” νšŸμˆ˜κ°€ 0인 κ²½μš°λŠ” 닡이 μ—†λŠ” 것이 λͺ…ν™•ν•˜κΈ° λ•Œλ¬Έμ— μ œμ™Έν•œλ‹€.
  • ν˜„μž¬ μœ„μΉ˜λ₯Ό κΈ°μ€€μœΌλ‘œ 동, μ„œ, 남, 뢁 각 λ°©ν–₯으둜 νƒμƒ‰ν•˜λ©΄μ„œ 곡간 μ™ΈλΆ€λ‘œ λ„λ‹¬ν•˜λŠ” 경우의 수λ₯Ό μ°ΎλŠ”λ‹€.
    • μ„œ (-1, 0), 동 (1, 0), 뢁 (0, -1), 남 (0, 1) 각 λ°©ν–₯에 λŒ€ν•œ μ›€μ§μž„μ„ 미리 λ°°μ—΄ delta에 λ‹΄μ•„λ‘”λ‹€.
    • κ³΅κ°„μ—μ„œ λ²—μ–΄λ‚œ κ²½μš°μ—λŠ” μœ νš¨ν•œ κ²°κ³Όμ΄λ―€λ‘œ 값을 1둜 ν•œλ‹€.
    • 더 이상 움직일 수 μ—†λŠ” 경우 move == 0μ—λŠ” 값을 0으둜 ν•œλ‹€.
    • 각 λ°©ν–₯으둜 μ‹œλ„ν•˜μ—¬ κ³΅κ°„μ—μ„œ λ²—μ–΄λ‚œ 경우의 수λ₯Ό λͺ¨λ‘ λ”ν•œλ‹€.
  • ν˜„μž¬κΉŒμ§€ 움직인 횟수 move + ν˜„μž¬ μœ„μΉ˜ (i, j) λ³„λ‘œ 곡간 외뢀에 λ„λ‹¬ν•˜λŠ” 경우의 μˆ˜λŠ” 맀번 계산해도 λ™μΌν•˜κ²Œ λ‚˜μ˜€κΈ° λ•Œλ¬Έμ— memoization을 ν™œμš©ν•œλ‹€.
    • 3차원 λ°°μ—΄ dp을 μƒμ„±ν•˜μ—¬ ν˜„μž¬κΉŒμ§€ 움직인 횟수 move - 1, x μ’Œν‘œ i, y μ’Œν‘œ j λ³„λ‘œ 곡간 외뢀에 λ„λ‹¬ν•˜λŠ” 경우의 수λ₯Ό μ €μž₯ν•œλ‹€.
    • 이미 μ €μž₯된 경우의 수 dp[move - 1][i][j]κ°€ μžˆλ‹€λ©΄ κ³„μ‚°ν•˜μ§€ μ•Šκ³  λ°”λ‘œ 값을 κΊΌλ‚΄μ„œ λŒλ €μ€€λ‹€.
class Solution { final int MOD = 1_000_000_000 + 7; final int[][] delta = new int[][] { {-1, 0}, { 1, 0}, { 0, -1}, { 0, 1}, }; int traverse(int[][][] dp, int i, int j, int move) { if (i < 0 || j < 0 || i >= dp[0].length || j >= dp[0][0].length) { return 1; } else if (move == 0) { return 0; } else if (dp[move - 1][i][j] != -1) { return dp[move - 1][i][j]; } int result = 0; for (int[] d : delta) { result = (result + traverse(dp, i + d[0], j + d[1], move - 1)) % MOD; } return dp[move - 1][i][j] = result; } public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) { if (maxMove == 0) { return 0; } int[][][] dp = new int[maxMove][m][n]; for (int[][] sub : dp) { for (int[] subsub : sub) { Arrays.fill(subsub, -1); } } return traverse(dp, startRow, startColumn, maxMove); } }
  • dp μ΄ˆκΈ°ν™” λΆ€λΆ„μ—μ„œ stream을 ν™œμš©ν•˜λ©΄ 더 μ½”λ“œκ°€ κΉ”λ”ν•΄μ§€κΈ°λŠ” ν•˜μ§€λ§Œ μ„±λŠ₯ 차이가 κ½€ μžˆμ–΄μ„œ for loop 방식을 μ‚¬μš©ν•˜λŠ”κ²Œ 더 λ‚«λ‹€.
class Solution { ... omitted .., public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) { if (maxMove == 0) { return 0; } int[][][] dp = new int[maxMove][m][n]; Arrays.stream(dp) .flatMap(Arrays::stream) .forEach((a) -> Arrays.fill(a, -1)); return traverse(dp, startRow, startColumn, maxMove); } }