[Swift]LeetCode864. 獲取全部鑰匙的最短路徑 | Shortest Path to Get All Keys

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

We are given a 2-dimensional grid"." is an empty cell, "#" is a wall, "@" is the starting point, ("a""b", ...) are keys, and ("A""B", ...) are locks.git

We start at the starting point, and one move consists of walking one space in one of the 4 cardinal directions.  We cannot walk outside the grid, or walk into a wall.  If we walk over a key, we pick it up.  We can't walk over a lock unless we have the corresponding key.github

For some 1 <= K <= 6, there is exactly one lowercase and one uppercase letter of the first Kletters of the English alphabet in the grid.  This means that there is exactly one key for each lock, and one lock for each key; and also that the letters used to represent the keys and locks were chosen in the same order as the English alphabet.數組

Return the lowest number of moves to acquire all keys.  If it's impossible, return -1微信

Example 1:app

Input: ["@.a.#","###.#","b.A.B"]
Output: 8 

Example 2:less

Input: ["@..aA","..B#.","....b"]
Output: 6 

Note:ide

  1. 1 <= grid.length <= 30
  2. 1 <= grid[0].length <= 30
  3. grid[i][j] contains only'.''#''@''a'-'f' and 'A'-'F'
  4. The number of keys is in [1, 6].  Each key has a different letter and opens exactly one lock.

給定一個二維網格 grid。 "." 表明一個空房間, "#" 表明一堵牆, "@" 是起點,("a""b", ...)表明鑰匙,("A""B", ...)表明鎖。函數

咱們從起點開始出發,一次移動是指向四個基本方向之一行走一個單位空間。咱們不能在網格外面行走,也沒法穿過一堵牆。若是途經一個鑰匙,咱們就把它撿起來。除非咱們手裏有對應的鑰匙,不然沒法經過鎖。post

假設 K 爲鑰匙/鎖的個數,且知足 1 <= K <= 6,字母表中的前 K 個字母在網格中都有本身對應的一個小寫和一個大寫字母。換言之,每一個鎖有惟一對應的鑰匙,每一個鑰匙也有惟一對應的鎖。另外,表明鑰匙和鎖的字母互爲大小寫並按字母順序排列。

返回獲取全部鑰匙所須要的移動的最少次數。若是沒法獲取全部鑰匙,返回 -1 。 

示例 1:

輸入:["@.a.#","###.#","b.A.B"]
輸出:8

示例 2:

輸入:["@..aA","..B#.","....b"]
輸出:6 

提示:

  1. 1 <= grid.length <= 30
  2. 1 <= grid[0].length <= 30
  3. grid[i][j] 只含有 '.''#''@''a'-'f' 以及 'A'-'F'
  4. 鑰匙的數目範圍是 [1, 6],每一個鑰匙都對應一個不一樣的字母,正好打開一個對應的鎖。

Runtime: 532 ms
Memory Usage: 20.5 MB
  1 class Solution {
  2     func shortestPathAllKeys(_ grid: [String]) -> Int {
  3         var x:Int = -1
  4         var y:Int = -1
  5         var m:Int = grid.count
  6         var n:Int = grid[0].count
  7         var maxNum:Int = -1
  8         for i in 0..<m
  9         {
 10             for j in 0..<n
 11             {
 12                 var c:Character = grid[i][j]
 13                 if c == "@"
 14                 {
 15                     x = i
 16                     y = j
 17                 }
 18                 if c >= "a" && c <= "f"
 19                 {
 20                     maxNum = max(c.ascii - 97 + 1, maxNum)
 21                 }
 22             }
 23         }
 24         var start:State = State(0, x, y)
 25         var q:[State] = [State]()
 26         var visited:Set<String> = Set<String>()
 27         visited.insert(String(0) + " " + String(x) + " " + String(y))
 28         q.append(start)
 29         var dirs:[[Int]] = [[0, 1],[1, 0],[0, -1],[-1, 0]]
 30         var step:Int = 0
 31         while (!q.isEmpty)
 32         {
 33             var size:Int = q.count
 34             while(size-- > 0)
 35             {
 36                 var cur:State = q.removeFirst()
 37                 if cur.keys == ((1 << maxNum) - 1) 
 38                 {
 39                     return step
 40                 }
 41                 for dir in dirs
 42                 {
 43                     var i:Int = cur.i + dir[0]
 44                     var j:Int = cur.j + dir[1]
 45                     var keys:Int = cur.keys
 46                     if i >= 0 && i < m && j >= 0 && j < n
 47                     {
 48                         var c:Character = grid[i][j]
 49                         if c == "#"
 50                         {
 51                             continue
 52                         }
 53                         if c >= "a" && c <= "f"
 54                         {
 55                             keys |= 1 << (c.ascii - 97)
 56                         }
 57                         if c >= "A" && c <= "F" && ((keys >> (c.ascii - 65)) & 1) == 0
 58                         {
 59                             continue
 60                         }
 61                         var str:String = String(keys) + " " + String(i) + " " + String(j)
 62                         if !visited.contains(str)
 63                         {
 64                             visited.insert(str)
 65                             q.append(State(keys, i, j))
 66                         }
 67                     }
 68                 }                
 69             }
 70             step += 1            
 71         }
 72         return -1        
 73     }
 74 }
 75 
 76 class State
 77 {
 78     var keys:Int
 79     var i:Int
 80     var j:Int 
 81     init(_ keys:Int,_ i:Int,_ j:Int)
 82     {
 83         self.keys = keys
 84         self.i = i
 85         self.j = j
 86     }
 87 }
 88 
 89 //String擴展
 90 extension String {        
 91     //subscript函數能夠檢索數組中的值
 92     //直接按照索引方式截取指定索引的字符
 93     subscript (_ i: Int) -> Character {
 94         //讀取字符
 95         get {return self[index(startIndex, offsetBy: i)]}
 96     }
 97 }
 98 
 99 //Character擴展 
100 extension Character  
101 {  
102   //Character轉ASCII整數值(定義小寫爲整數值)
103    var ascii: Int {
104        get {
105            return Int(self.unicodeScalars.first?.value ?? 0)
106        }       
107     }
108 }
109 
110 /*擴展Int類,實現自增++、自減--運算符*/
111 extension Int{
112     //後綴--:先執行表達式後再自減
113     static postfix func --(num:inout Int) -> Int {
114         //輸入輸出參數num
115         let temp = num
116         //num減1
117         num -= 1
118          //返回減1前的數值
119         return temp
120     }
121 }
相關文章
相關標籤/搜索