@@ -89,6 +89,7 @@ fn update_point(
8989 passed : & mut Matrix < bool > ,
9090 booster_map : & mut Matrix < Option < BoosterType > > ,
9191 hand_count : & mut usize ,
92+ tele_count : & mut usize ,
9293 remaining : & mut usize ,
9394) {
9495 bodies_diff. iter ( ) . map ( |diff| point + * diff) . for_each ( |b| {
@@ -100,6 +101,7 @@ fn update_point(
100101 if let Some ( Some ( kind) ) = booster_map. get ( point) {
101102 match kind {
102103 BoosterType :: NewHand => * hand_count += 1 ,
104+ BoosterType :: Teleports => * tele_count += 1 ,
103105 BoosterType :: Drill => { }
104106 _ => { }
105107 }
@@ -156,6 +158,8 @@ pub fn solve_small(task: Task) -> Vec<Command> {
156158 ] ) ;
157159
158160 let mut hand_count = 0 ;
161+ let mut tele_count = 0 ;
162+ let mut tele_points = Vec :: new ( ) ;
159163
160164 while remaining > 0 {
161165 while hand_count > 0 && !new_bodies. is_empty ( ) {
@@ -164,15 +168,24 @@ pub fn solve_small(task: Task) -> Vec<Command> {
164168 bodies_diff. push ( new_hand) ;
165169 res. push ( Command :: NewHand ( new_hand) ) ;
166170 }
171+
172+ if tele_count > 0 {
173+ tele_points. push ( current_point) ;
174+ tele_count -= 1 ;
175+ res. push ( Command :: ResetBeacon ) ;
176+ }
177+
167178 update_point (
168179 current_point,
169180 & bodies_diff,
170181 & mut passed,
171182 & mut booster_map,
172183 & mut hand_count,
184+ & mut tele_count,
173185 & mut remaining,
174186 ) ;
175- let moves = find_shortest_path (
187+
188+ let base_moves = find_shortest_path (
176189 width,
177190 height,
178191 & valid,
@@ -181,6 +194,34 @@ pub fn solve_small(task: Task) -> Vec<Command> {
181194 & bodies_diff,
182195 & booster_map,
183196 ) ;
197+
198+ let tele_moves = tele_points
199+ . iter ( )
200+ . map ( |start| {
201+ (
202+ start,
203+ find_shortest_path (
204+ width,
205+ height,
206+ & valid,
207+ & passed,
208+ * start,
209+ & bodies_diff,
210+ & booster_map,
211+ ) ,
212+ )
213+ } )
214+ . min_by_key ( |( _, v) | v. len ( ) ) ;
215+
216+ let moves = match tele_moves {
217+ Some ( ( tele_point, ref tele_moves) ) if tele_moves. len ( ) + 1 < base_moves. len ( ) => {
218+ res. push ( Command :: ShiftBeacon ( * tele_point) ) ;
219+ current_point = * tele_point;
220+ tele_moves
221+ }
222+ _ => & base_moves,
223+ } ;
224+
184225 for m in moves {
185226 current_point = current_point. move_with ( & m) ;
186227 update_point (
@@ -189,9 +230,10 @@ pub fn solve_small(task: Task) -> Vec<Command> {
189230 & mut passed,
190231 & mut booster_map,
191232 & mut hand_count,
233+ & mut tele_count,
192234 & mut remaining,
193235 ) ;
194- res. push ( Command :: Move ( m) ) ;
236+ res. push ( Command :: Move ( m. clone ( ) ) ) ;
195237 }
196238 }
197239
0 commit comments