@@ -88,35 +88,44 @@ tags:
88
88
89
89
### 方法一:BFS
90
90
91
+ 我们可以使用广度优先搜索的方法,从起点开始,每次向前走 1 到 6 步,然后判断是否有蛇或梯子,如果有,就走到蛇或梯子的目的地,否则就走到下一个方格。
92
+
93
+ 具体地,我们使用一个队列 $\textit{q}$ 来存储当前可以到达的方格编号,初始时将编号 $1$ 放入队列。同时我们使用一个集合 $\textit{vis}$ 来记录已经到达过的方格,避免重复访问,初始时将编号 $1$ 加入集合 $\textit{vis}$。
94
+
95
+ 在每一次的操作中,我们取出队首的方格编号 $x$,如果 $x$ 是终点,那么我们就可以返回当前的步数。否则我们将 $x$ 向前走 $1$ 到 $6$ 步,设新的编号为 $y$,如果 $y$ 落在棋盘外,那么我们就直接跳过。否则,我们需要找到 $y$ 对应的行和列,由于行的编号是从下到上递减的,而列的编号与行的奇偶性有关,因此我们需要进行一些计算得到 $y$ 对应的行和列。
96
+
97
+ 如果 $y$ 对应的方格上有蛇或梯子,那么我们需要额外走到蛇或梯子的目的地,设其为 $z$。如果 $z$ 没有被访问过,我们就将 $z$ 加入队列和集合中,这样我们就可以继续进行广度优先搜索。
98
+
99
+ 如果我们最终无法到达终点,那么我们就返回 $-1$。
100
+
101
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 是棋盘的边长。
102
+
91
103
<!-- tabs:start -->
92
104
93
105
#### Python3
94
106
95
107
``` python
96
108
class Solution :
97
109
def snakesAndLadders (self , board : List[List[int ]]) -> int :
98
- def get (x ):
99
- i, j = (x - 1 ) // n, (x - 1 ) % n
100
- if i & 1 :
101
- j = n - 1 - j
102
- return n - 1 - i, j
103
-
104
110
n = len (board)
105
111
q = deque([1 ])
106
112
vis = {1 }
107
113
ans = 0
114
+ m = n * n
108
115
while q:
109
116
for _ in range (len (q)):
110
- curr = q.popleft()
111
- if curr == n * n :
117
+ x = q.popleft()
118
+ if x == m :
112
119
return ans
113
- for next in range (curr + 1 , min (curr + 7 , n * n + 1 )):
114
- i, j = get(next )
115
- if board[i][j] != - 1 :
116
- next = board[i][j]
117
- if next not in vis:
118
- q.append(next )
119
- vis.add(next )
120
+ for y in range (x + 1 , min (x + 6 , m) + 1 ):
121
+ i, j = divmod (y - 1 , n)
122
+ if i & 1 :
123
+ j = n - j - 1
124
+ i = n - i - 1
125
+ z = y if board[i][j] == - 1 else board[i][j]
126
+ if z not in vis:
127
+ vis.add(z)
128
+ q.append(z)
120
129
ans += 1
121
130
return - 1
122
131
```
@@ -125,46 +134,35 @@ class Solution:
125
134
126
135
``` java
127
136
class Solution {
128
- private int n;
129
-
130
137
public int snakesAndLadders (int [][] board ) {
131
- n = board. length;
138
+ int n = board. length;
132
139
Deque<Integer > q = new ArrayDeque<> ();
133
140
q. offer(1 );
134
- boolean [] vis = new boolean [n * n + 1 ];
141
+ int m = n * n;
142
+ boolean [] vis = new boolean [m + 1 ];
135
143
vis[1 ] = true ;
136
- int ans = 0 ;
137
- while (! q. isEmpty()) {
138
- for (int t = q. size(); t > 0 ; -- t) {
139
- int curr = q. poll();
140
- if (curr == n * n) {
144
+ for (int ans = 0 ; ! q. isEmpty(); ++ ans) {
145
+ for (int k = q. size(); k > 0 ; -- k) {
146
+ int x = q. poll();
147
+ if (x == m) {
141
148
return ans;
142
149
}
143
- for (int k = curr + 1 ; k <= Math . min(curr + 6 , n * n); ++ k) {
144
- int [] p = get(k);
145
- int next = k;
146
- int i = p[0 ], j = p[1 ];
147
- if (board[i][j] != - 1 ) {
148
- next = board[i][j];
150
+ for (int y = x + 1 ; y <= Math . min(x + 6 , m); ++ y) {
151
+ int i = (y - 1 ) / n, j = (y - 1 ) % n;
152
+ if (i % 2 == 1 ) {
153
+ j = n - j - 1 ;
149
154
}
150
- if (! vis[next]) {
151
- vis[next] = true ;
152
- q. offer(next);
155
+ i = n - i - 1 ;
156
+ int z = board[i][j] == - 1 ? y : board[i][j];
157
+ if (! vis[z]) {
158
+ vis[z] = true ;
159
+ q. offer(z);
153
160
}
154
161
}
155
162
}
156
- ++ ans;
157
163
}
158
164
return - 1 ;
159
165
}
160
-
161
- private int [] get (int x ) {
162
- int i = (x - 1 ) / n, j = (x - 1 ) % n;
163
- if (i % 2 == 1 ) {
164
- j = n - 1 - j;
165
- }
166
- return new int [] {n - 1 - i, j};
167
- }
168
166
}
169
167
```
170
168
@@ -173,40 +171,36 @@ class Solution {
173
171
``` cpp
174
172
class Solution {
175
173
public:
176
- int n;
177
-
178
174
int snakesAndLadders(vector<vector<int >>& board) {
179
- n = board.size();
175
+ int n = board.size();
180
176
queue<int > q{{1}};
181
- vector<bool> vis(n * n + 1);
177
+ int m = n * n;
178
+ vector<bool > vis(m + 1);
182
179
vis[ 1] = true;
183
- int ans = 0;
184
- while (!q.empty()) {
185
- for (int t = q.size(); t; --t) {
186
- int curr = q.front();
187
- if (curr == n * n) return ans;
180
+
181
+ for (int ans = 0; !q.empty(); ++ans) {
182
+ for (int k = q.size(); k > 0; --k) {
183
+ int x = q.front();
188
184
q.pop();
189
- for (int k = curr + 1; k <= min(curr + 6, n * n); ++k) {
190
- auto p = get(k);
191
- int next = k;
192
- int i = p[0], j = p[1];
193
- if (board[i][j] != -1) next = board[i][j];
194
- if (!vis[next]) {
195
- vis[next] = true;
196
- q.push(next);
185
+ if (x == m) {
186
+ return ans;
187
+ }
188
+ for (int y = x + 1 ; y <= min(x + 6 , m); ++y) {
189
+ int i = (y - 1) / n, j = (y - 1) % n;
190
+ if (i % 2 == 1) {
191
+ j = n - j - 1;
192
+ }
193
+ i = n - i - 1;
194
+ int z = board[i][j] == -1 ? y : board[i][j];
195
+ if (!vis[z]) {
196
+ vis[z] = true;
197
+ q.push(z);
197
198
}
198
199
}
199
200
}
200
- ++ans;
201
201
}
202
202
return -1;
203
203
}
204
-
205
- vector<int > get (int x) {
206
- int i = (x - 1) / n, j = (x - 1) % n;
207
- if (i % 2 == 1) j = n - 1 - j;
208
- return {n - 1 - i, j};
209
- }
210
204
};
211
205
```
212
206
@@ -215,43 +209,78 @@ public:
215
209
``` go
216
210
func snakesAndLadders (board [][]int ) int {
217
211
n := len (board)
218
- get := func(x int) []int {
219
- i, j := (x-1)/n, (x-1)%n
220
- if i%2 == 1 {
221
- j = n - 1 - j
222
- }
223
- return []int{n - 1 - i, j}
224
- }
225
212
q := []int {1 }
226
- vis := make([]bool, n*n+1)
213
+ m := n * n
214
+ vis := make ([]bool , m+1 )
227
215
vis[1 ] = true
228
- ans := 0
229
- for len(q) > 0 {
230
- for t := len(q); t > 0; t-- {
231
- curr := q[0]
232
- if curr == n*n {
216
+
217
+ for ans := 0 ; len (q) > 0 ; ans++ {
218
+ for k := len (q); k > 0 ; k-- {
219
+ x := q[0 ]
220
+ q = q[1 :]
221
+ if x == m {
233
222
return ans
234
223
}
235
- q = q[1:]
236
- for k := curr + 1; k <= curr+6 && k <= n*n; k++ {
237
- p := get(k)
238
- next := k
239
- i, j := p[0], p[1]
224
+ for y := x + 1 ; y <= min (x+6 , m); y++ {
225
+ i , j := (y-1 )/n, (y-1 )%n
226
+ if i%2 == 1 {
227
+ j = n - j - 1
228
+ }
229
+ i = n - i - 1
230
+ z := y
240
231
if board[i][j] != -1 {
241
- next = board[i][j]
232
+ z = board[i][j]
242
233
}
243
- if !vis[next ] {
244
- vis[next ] = true
245
- q = append(q, next )
234
+ if !vis[z ] {
235
+ vis[z ] = true
236
+ q = append (q, z )
246
237
}
247
238
}
248
239
}
249
- ans++
250
240
}
251
241
return -1
252
242
}
253
243
```
254
244
245
+ #### TypeScript
246
+
247
+ ``` ts
248
+ function snakesAndLadders(board : number [][]): number {
249
+ const n = board .length ;
250
+ const q: number [] = [1 ];
251
+ const m = n * n ;
252
+ const vis: boolean [] = Array (m + 1 ).fill (false );
253
+ vis [1 ] = true ;
254
+
255
+ for (let ans = 0 ; q .length > 0 ; ans ++ ) {
256
+ const nq: number [] = [];
257
+ for (const x of q ) {
258
+ if (x === m ) {
259
+ return ans ;
260
+ }
261
+ for (let y = x + 1 ; y <= Math .min (x + 6 , m ); y ++ ) {
262
+ let i = Math .floor ((y - 1 ) / n );
263
+ let j = (y - 1 ) % n ;
264
+ if (i % 2 === 1 ) {
265
+ j = n - j - 1 ;
266
+ }
267
+ i = n - i - 1 ;
268
+ const z = board [i ][j ] === - 1 ? y : board [i ][j ];
269
+ if (! vis [z ]) {
270
+ vis [z ] = true ;
271
+ nq .push (z );
272
+ }
273
+ }
274
+ }
275
+ q .length = 0 ;
276
+ for (const x of nq ) {
277
+ q .push (x );
278
+ }
279
+ }
280
+ return - 1 ;
281
+ }
282
+ ```
283
+
255
284
<!-- tabs:end -->
256
285
257
286
<!-- solution:end -->
0 commit comments