Skip to content

Commit 3c59bf1

Browse files
committed
添加 problem 864
1 parent 283359f commit 3c59bf1

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
package leetcode
2+
3+
import (
4+
"math"
5+
"strings"
6+
)
7+
8+
// 解法一 BFS,利用状态压缩来过滤筛选状态
9+
func shortestPathAllKeys(grid []string) int {
10+
if len(grid) == 0 {
11+
return 0
12+
}
13+
board, visited, startx, starty, res, fullKeys := make([][]byte, len(grid)), make([][][]bool, len(grid)), 0, 0, 0, 0
14+
for i := 0; i < len(grid); i++ {
15+
board[i] = make([]byte, len(grid[0]))
16+
}
17+
for i, g := range grid {
18+
board[i] = []byte(g)
19+
for _, v := range g {
20+
if v == 'a' || v == 'b' || v == 'c' || v == 'd' || v == 'e' || v == 'f' {
21+
fullKeys |= (1 << uint(v-'a'))
22+
}
23+
}
24+
if strings.Contains(g, "@") {
25+
startx, starty = i, strings.Index(g, "@")
26+
}
27+
}
28+
for i := 0; i < len(visited); i++ {
29+
visited[i] = make([][]bool, len(board[0]))
30+
}
31+
for i := 0; i < len(board); i++ {
32+
for j := 0; j < len(board[0]); j++ {
33+
visited[i][j] = make([]bool, 64)
34+
}
35+
}
36+
queue := []int{}
37+
queue = append(queue, (starty<<16)|(startx<<8))
38+
visited[startx][starty][0] = true
39+
for len(queue) != 0 {
40+
qLen := len(queue)
41+
for i := 0; i < qLen; i++ {
42+
state := queue[0]
43+
queue = queue[1:]
44+
starty, startx = state>>16, (state>>8)&0xFF
45+
keys := state & 0xFF
46+
if keys == fullKeys {
47+
return res
48+
}
49+
for i := 0; i < 4; i++ {
50+
newState := keys
51+
nx := startx + dir[i][0]
52+
ny := starty + dir[i][1]
53+
if !isInBoard(board, nx, ny) {
54+
continue
55+
}
56+
if board[nx][ny] == '#' {
57+
continue
58+
}
59+
flag, canThroughLock := keys&(1<<(board[nx][ny]-'A')), false
60+
if flag != 0 {
61+
canThroughLock = true
62+
}
63+
if isLock(board, nx, ny) && !canThroughLock {
64+
continue
65+
}
66+
if isKey(board, nx, ny) {
67+
newState |= (1 << (board[nx][ny] - 'a'))
68+
}
69+
if visited[nx][ny][newState] {
70+
continue
71+
}
72+
queue = append(queue, (ny<<16)|(nx<<8)|newState)
73+
visited[nx][ny][newState] = true
74+
}
75+
}
76+
res++
77+
}
78+
return -1
79+
}
80+
81+
// 解法二 DFS,但是超时了,剪枝条件不够强
82+
func shortestPathAllKeys1(grid []string) int {
83+
if len(grid) == 0 {
84+
return 0
85+
}
86+
board, visited, startx, starty, res, fullKeys := make([][]byte, len(grid)), make([][][]bool, len(grid)), 0, 0, math.MaxInt64, 0
87+
for i := 0; i < len(grid); i++ {
88+
board[i] = make([]byte, len(grid[0]))
89+
}
90+
for i, g := range grid {
91+
board[i] = []byte(g)
92+
for _, v := range g {
93+
if v == 'a' || v == 'b' || v == 'c' || v == 'd' || v == 'e' || v == 'f' {
94+
fullKeys |= (1 << uint(v-'a'))
95+
}
96+
}
97+
if strings.Contains(g, "@") {
98+
startx, starty = i, strings.Index(g, "@")
99+
}
100+
}
101+
for i := 0; i < len(visited); i++ {
102+
visited[i] = make([][]bool, len(board[0]))
103+
}
104+
for i := 0; i < len(board); i++ {
105+
for j := 0; j < len(board[0]); j++ {
106+
visited[i][j] = make([]bool, 64)
107+
}
108+
}
109+
searchKeys(board, &visited, fullKeys, 0, (starty<<16)|(startx<<8), &res, []int{})
110+
if res == math.MaxInt64 {
111+
return -1
112+
}
113+
return res - 1
114+
}
115+
116+
func searchKeys(board [][]byte, visited *[][][]bool, fullKeys, step, state int, res *int, path []int) {
117+
y, x := state>>16, (state>>8)&0xFF
118+
keys := state & 0xFF
119+
120+
if keys == fullKeys {
121+
*res = min(*res, step)
122+
return
123+
}
124+
125+
flag, canThroughLock := keys&(1<<(board[x][y]-'A')), false
126+
if flag != 0 {
127+
canThroughLock = true
128+
}
129+
newState := keys
130+
//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)
131+
if (board[x][y] != '#' && !isLock(board, x, y)) || (isLock(board, x, y) && canThroughLock) {
132+
if isKey(board, x, y) {
133+
newState |= (1 << uint(board[x][y]-'a'))
134+
}
135+
(*visited)[x][y][newState] = true
136+
path = append(path, x)
137+
path = append(path, y)
138+
139+
for i := 0; i < 4; i++ {
140+
nx := x + dir[i][0]
141+
ny := y + dir[i][1]
142+
if isInBoard(board, nx, ny) && !(*visited)[nx][ny][newState] {
143+
searchKeys(board, visited, fullKeys, step+1, (ny<<16)|(nx<<8)|newState, res, path)
144+
}
145+
}
146+
(*visited)[x][y][keys] = false
147+
path = path[:len(path)-1]
148+
path = path[:len(path)-1]
149+
}
150+
}
151+
152+
func isLock(board [][]byte, x, y int) bool {
153+
if (board[x][y] == 'A') || (board[x][y] == 'B') ||
154+
(board[x][y] == 'C') || (board[x][y] == 'D') ||
155+
(board[x][y] == 'E') || (board[x][y] == 'F') {
156+
return true
157+
}
158+
return false
159+
}
160+
161+
func isKey(board [][]byte, x, y int) bool {
162+
if (board[x][y] == 'a') || (board[x][y] == 'b') ||
163+
(board[x][y] == 'c') || (board[x][y] == 'd') ||
164+
(board[x][y] == 'e') || (board[x][y] == 'f') {
165+
return true
166+
}
167+
return false
168+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package leetcode
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
type question864 struct {
9+
para864
10+
ans864
11+
}
12+
13+
// para 是参数
14+
// one 代表第一个参数
15+
type para864 struct {
16+
one []string
17+
}
18+
19+
// ans 是答案
20+
// one 代表第一个答案
21+
type ans864 struct {
22+
one int
23+
}
24+
25+
func Test_Problem864(t *testing.T) {
26+
27+
qs := []question864{
28+
29+
question864{
30+
para864{[]string{".##..##..B", "##...#...#", "..##..#...", ".#..#b...#", "#.##.a.###", ".#....#...", ".##..#.#..", ".....###@.", "..........", ".........A"}},
31+
ans864{11},
32+
},
33+
34+
question864{
35+
para864{[]string{"Dd#b@", ".fE.e", "##.B.", "#.cA.", "aF.#C"}},
36+
ans864{14},
37+
},
38+
39+
question864{
40+
para864{[]string{"@...a", ".###A", "b.BCc"}},
41+
ans864{10},
42+
},
43+
44+
question864{
45+
para864{[]string{"@Aa"}},
46+
ans864{-1},
47+
},
48+
49+
question864{
50+
para864{[]string{"b", "A", "a", "@", "B"}},
51+
ans864{3},
52+
},
53+
54+
question864{
55+
para864{[]string{"@.a.#", "#####", "b.A.B"}},
56+
ans864{-1},
57+
},
58+
59+
question864{
60+
para864{[]string{"@.a.#", "###.#", "b.A.B"}},
61+
ans864{8},
62+
},
63+
64+
question864{
65+
para864{[]string{"@..aA", "..B#.", "....b"}},
66+
ans864{6},
67+
},
68+
}
69+
70+
fmt.Printf("------------------------Leetcode Problem 864------------------------\n")
71+
72+
for _, q := range qs {
73+
_, p := q.ans864, q.para864
74+
fmt.Printf("【input】:%v 【output】:%v\n", p, shortestPathAllKeys(p.one))
75+
}
76+
fmt.Printf("\n\n\n")
77+
}

0 commit comments

Comments
 (0)