[Swift]LeetCode174. 地下城遊戲 | Dungeon Game

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-zprzotpv-md.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess.git

The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately.github

Some of the rooms are guarded by demons, so the knight loses health (negative integers) upon entering these rooms; other rooms are either empty (0's) or contain magic orbs that increase the knight's health (positive integers).微信

In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step.ide

 

Write a function to determine the knight's minimum initial health so that he is able to rescue the princess.函數

For example, given the dungeon below, the initial health of the knight must be at least 7 if he follows the optimal path RIGHT-> RIGHT -> DOWN -> DOWN.佈局

-2 (K) -3 3
-5 -10 1
10 30 -5 (P)

Note:ui

  • The knight's health has no upper bound.
  • Any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where the princess is imprisoned.

一些惡魔抓住了公主(P)並將她關在了地下城的右下角。地下城是由 M x N 個房間組成的二維網格。咱們英勇的騎士(K)最初被安置在左上角的房間裏,他必須穿過地下城並經過對抗惡魔來拯救公主。spa

騎士的初始健康點數爲一個正整數。若是他的健康點數在某一時刻降至 0 或如下,他會當即死亡。code

有些房間由惡魔守衛,所以騎士在進入這些房間時會失去健康點數(若房間裏的值爲負整數,則表示騎士將損失健康點數);其餘房間要麼是空的(房間裏的值爲 0),要麼包含增長騎士健康點數的魔法球(若房間裏的值爲正整數,則表示騎士將增長健康點數)。

爲了儘快到達公主,騎士決定每次只向右或向下移動一步。

 

編寫一個函數來計算確保騎士可以拯救到公主所需的最低初始健康點數。

例如,考慮到以下佈局的地下城,若是騎士遵循最佳路徑 右 -> 右 -> 下 -> 下,則騎士的初始健康點數至少爲 7。

-2 (K) -3 3
-5 -10 1
10 30 -5 (P)

說明:

  • 騎士的健康點數沒有上限。

  • 任何房間均可能對騎士的健康點數形成威脅,也可能增長騎士的健康點數,包括騎士進入的左上角房間以及公主被監禁的右下角房間。

56ms

 1 class Solution {
 2     func calculateMinimumHP(_ dungeon: [[Int]]) -> Int {
 3         var m:Int = dungeon.count
 4         var n:Int = dungeon[0].count
 5         var dp:[Int] = [Int](repeating:Int.max,count:n + 1)
 6         dp[n - 1] = 1
 7         for i in (0..<m).reversed()
 8         {
 9             for j in (0..<n).reversed()
10             {
11                 dp[j] = max(1, min(dp[j], dp[j + 1]) - dungeon[i][j])
12             }
13         }
14         return dp[0]
15     }
16 }

60ms

 1 class Solution {
 2     
 3     func calculateMinimumHP(_ dungeon: [[Int]]) -> Int {
 4         let n = dungeon.count
 5         if n > 0 {
 6             let m = dungeon[0].count
 7             var c = [[Int]](repeating:[Int](repeating: .max, count: m + 1), count: n + 1)
 8             c[n][m-1] = 0
 9             c[n-1][m] = 0
10             for i in stride(from: n-1, through: 0, by: -1) {
11                 for j in stride(from: m-1, through: 0, by: -1) {
12                     let next = min(c[i+1][j],c[i][j+1])
13                     var cur = -dungeon[i][j] + next
14                     cur = max(cur, 0)
15                     c[i][j] = cur
16                 }
17             }
18             return c[0][0] + 1
19         } else {
20             return 1
21         }
22     }
23 }

60ms

 1 class Solution {
 2     func calculateMinimumHP(_ dungeon: [[Int]]) -> Int {
 3         
 4         let m = dungeon.count
 5         let n = dungeon[0].count
 6         
 7         var dp = Array(repeating: Array(repeating: 0, count: n), count: m)
 8     
 9         dp [m-1][n-1] = dungeon[m-1][n-1] < 0 ? -1 * dungeon[m-1][n-1] + 1 : 1
10         for i in stride(from: m-2, to: -1, by: -1) {
11             dp[i][n-1] = max(dp[i+1][n-1] - dungeon[i][n-1] , 1)
12         }
13         for j in stride(from: n-2, to: -1, by: -1) {
14             dp[m-1][j] = max(dp[m-1][j+1] - dungeon[m-1][j], 1)
15         }
16         
17         for i in stride(from: m-2, to: -1, by: -1) {
18             for j in stride(from: n-2, to: -1, by: -1) {
19                 let minIJ = min(dp[i][j+1], dp[i+1][j]) - dungeon[i][j]
20                 dp[i][j] = max(minIJ, 1)
21             }
22         }
23         
24         return  dp[0][0]
25     }
26 }

68ms

 1 class Solution {
 2     func calculateMinimumHP(_ dungeon: [[Int]]) -> Int {
 3         let rows = dungeon.count
 4         let cols = dungeon[0].count
 5         var dp = Array(repeating: Array(repeating: Int.max, count: cols + 1), count: rows + 1)
 6         
 7         dp[rows][cols - 1] = 1
 8         dp[rows - 1][cols] = 1
 9         
10         for i in stride(from: rows - 1, to: -1, by: -1 ) {
11             for j in stride(from: cols - 1, to: -1, by: -1 ) {
12                 let mv = min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]
13                 dp[i][j] = mv <= 0 ? 1 : mv
14             }
15         }
16         print(dp)        
17         return dp[0][0]
18     }
19 }

80ms

 1 class Solution {
 2     var result: [[Int]]!
 3     var flag: [[Bool]]!
 4     func calculateMinimumHP(_ dungeon: [[Int]]) -> Int {
 5         let row = dungeon.count
 6         let column = dungeon.first!.count
 7         result = Array(repeatElement(Array(repeatElement(0, count: column)), count: row))
 8         flag = Array(repeatElement(Array(repeatElement(false, count: column)), count: row))
 9         flag[row - 1][column - 1] = true
10         result[row - 1][column - 1] = dungeon[row - 1][column - 1]
11         
12         let answer = calculateResult(dungeon)
13         return answer <= 0 ? 1 - answer : 1
14     }
15     
16     func calculateResult(_ dungeon: [[Int]], _ n: Int = 0, _ m: Int = 0) -> Int {
17         if n == dungeon.count || m == dungeon.first!.count {
18             return -Int.max
19         }
20         if flag[n][m] == false {
21             flag[n][m] = true
22             result[n][m] = dungeon[n][m] + max(min(0, calculateResult(dungeon, n, m + 1)),
23                                                min(0, calculateResult(dungeon, n + 1, m)))
24         }
25         return result[n][m]
26     }
27 }
相關文章
相關標籤/搜索