Shortest Path to Get All Keys Solutions in Go
Number 864
Difficulty Hard
Acceptance 40.2%
Link LeetCode
Other languages C++
Solutions
Go solution by halfrost/LeetCode-Go
package leetcodeimport ("math""strings")var dir = [][]int{{-1, 0},{0, 1},{1, 0},{0, -1},}// 解法一 BFS,利用状态压缩来过滤筛选状态func shortestPathAllKeys(grid []string) int {if len(grid) == 0 {return 0}board, visited, startx, starty, res, fullKeys := make([][]byte, len(grid)), make([][][]bool, len(grid)), 0, 0, 0, 0for i := 0; i < len(grid); i++ {board[i] = make([]byte, len(grid[0]))}for i, g := range grid {board[i] = []byte(g)for _, v := range g {if v == 'a' || v == 'b' || v == 'c' || v == 'd' || v == 'e' || v == 'f' {fullKeys |= (1 << uint(v-'a'))}}if strings.Contains(g, "@") {startx, starty = i, strings.Index(g, "@")}}for i := 0; i < len(visited); i++ {visited[i] = make([][]bool, len(board[0]))}for i := 0; i < len(board); i++ {for j := 0; j < len(board[0]); j++ {visited[i][j] = make([]bool, 64)}}queue := []int{}queue = append(queue, (starty<<16)|(startx<<8))visited[startx][starty][0] = truefor len(queue) != 0 {qLen := len(queue)for i := 0; i < qLen; i++ {state := queue[0]queue = queue[1:]starty, startx = state>>16, (state>>8)&0xFFkeys := state & 0xFFif keys == fullKeys {return res}for i := 0; i < 4; i++ {newState := keysnx := startx + dir[i][0]ny := starty + dir[i][1]if !isInBoard(board, nx, ny) {continue}if board[nx][ny] == '#' {continue}flag, canThroughLock := keys&(1<<(board[nx][ny]-'A')), falseif flag != 0 {canThroughLock = true}if isLock(board, nx, ny) && !canThroughLock {continue}if isKey(board, nx, ny) {newState |= (1 << (board[nx][ny] - 'a'))}if visited[nx][ny][newState] {continue}queue = append(queue, (ny<<16)|(nx<<8)|newState)visited[nx][ny][newState] = true}}res++}return -1}func isInBoard(board [][]byte, x, y int) bool {return x >= 0 && x < len(board) && y >= 0 && y < len(board[0])}// 解法二 DFS,但是超时了,剪枝条件不够强func shortestPathAllKeys1(grid []string) int {if len(grid) == 0 {return 0}board, visited, startx, starty, res, fullKeys := make([][]byte, len(grid)), make([][][]bool, len(grid)), 0, 0, math.MaxInt64, 0for i := 0; i < len(grid); i++ {board[i] = make([]byte, len(grid[0]))}for i, g := range grid {board[i] = []byte(g)for _, v := range g {if v == 'a' || v == 'b' || v == 'c' || v == 'd' || v == 'e' || v == 'f' {fullKeys |= (1 << uint(v-'a'))}}if strings.Contains(g, "@") {startx, starty = i, strings.Index(g, "@")}}for i := 0; i < len(visited); i++ {visited[i] = make([][]bool, len(board[0]))}for i := 0; i < len(board); i++ {for j := 0; j < len(board[0]); j++ {visited[i][j] = make([]bool, 64)}}searchKeys(board, &visited, fullKeys, 0, (starty<<16)|(startx<<8), &res, []int{})if res == math.MaxInt64 {return -1}return res - 1}func searchKeys(board [][]byte, visited *[][][]bool, fullKeys, step, state int, res *int, path []int) {y, x := state>>16, (state>>8)&0xFFkeys := state & 0xFFif keys == fullKeys {*res = min(*res, step)return}flag, canThroughLock := keys&(1<<(board[x][y]-'A')), falseif flag != 0 {canThroughLock = true}newState := keys//fmt.Printf("x = %v y = %v fullKeys = %v keys = %v step = %v res = %v path = %v state = %v\n", x, y, fullKeys, keys, step, *res, path, state)if (board[x][y] != '#' && !isLock(board, x, y)) || (isLock(board, x, y) && canThroughLock) {if isKey(board, x, y) {newState |= (1 << uint(board[x][y]-'a'))}(*visited)[x][y][newState] = truepath = append(path, x)path = append(path, y)for i := 0; i < 4; i++ {nx := x + dir[i][0]ny := y + dir[i][1]if isInBoard(board, nx, ny) && !(*visited)[nx][ny][newState] {searchKeys(board, visited, fullKeys, step+1, (ny<<16)|(nx<<8)|newState, res, path)}}(*visited)[x][y][keys] = falsepath = path[:len(path)-1]path = path[:len(path)-1]}}func isLock(board [][]byte, x, y int) bool {if (board[x][y] == 'A') || (board[x][y] == 'B') ||(board[x][y] == 'C') || (board[x][y] == 'D') ||(board[x][y] == 'E') || (board[x][y] == 'F') {return true}return false}func isKey(board [][]byte, x, y int) bool {if (board[x][y] == 'a') || (board[x][y] == 'b') ||(board[x][y] == 'c') || (board[x][y] == 'd') ||(board[x][y] == 'e') || (board[x][y] == 'f') {return true}return false}func min(a int, b int) int {if a > b {return b}return a}