11use std:: {
2- collections:: VecDeque ,
3- hash:: Hash ,
4- ops:: { Bound , RangeBounds } ,
5- str:: FromStr ,
2+ collections:: { BinaryHeap , VecDeque } , hash:: Hash , ops:: { Bound , RangeBounds } , str:: FromStr
63} ;
74
85use anyhow:: { Result , anyhow} ;
@@ -196,10 +193,6 @@ impl FromStr for Grid {
196193 }
197194}
198195
199- // I am aware that dist has no need to belong in this struct (the first 16 bits right now)
200- // But for some reason removing it decreases performances (2ms -> 8ms), this is obviously
201- // stupid: I am litterally removing code, but I guess this changes how the queue behaves
202- // (it really shouldn't but whatever).
203196#[ derive( Debug , Clone , Copy , Eq ) ]
204197struct State < const R : usize > {
205198 inner : u64 ,
@@ -233,6 +226,15 @@ impl<const R: usize> State<R> {
233226 }
234227 }
235228 #[ inline( always) ]
229+ fn with_dist ( self , dist : usize ) -> Self {
230+ debug_assert ! ( dist <= 65535 ) ;
231+ Self { inner : ( self . inner & !0xFFFF ) | dist as u64 }
232+ }
233+ #[ inline( always) ]
234+ fn dist ( self ) -> usize {
235+ ( self . inner & 0xFFFF ) as usize
236+ }
237+ #[ inline( always) ]
236238 fn keys ( self ) -> BitSet {
237239 BitSet {
238240 inner : ( self . inner >> 16 & 0x7FFFFFF ) as u32 ,
@@ -247,7 +249,7 @@ impl<const R: usize> State<R> {
247249impl < const R : usize > PartialEq for State < R > {
248250 #[ inline( always) ]
249251 fn eq ( & self , other : & Self ) -> bool {
250- ( self . inner ^ other. inner ) >> 16 == 0
252+ self . inner >> 16 == other. inner >> 16
251253 }
252254}
253255
@@ -409,21 +411,21 @@ impl<const R: usize> KeyGraph<R> {
409411
410412 fn explore ( & self ) -> usize {
411413 // Dijkstra on the simplified graph
412- let mut queue = PriorityQueue :: new ( ) ;
414+ let mut queue = BinaryHeap :: new ( ) ;
413415 let mut dist = FxHashMap :: with_capacity_and_hasher ( 131071 , FxBuildHasher :: default ( ) ) ;
414416 let start = State :: new ( 0 , [ self . count ; R ] , BitSet :: empty ( ) ) ;
415417 dist. insert ( start, 0 ) ;
416- queue. push ( 0 , start) ;
418+ queue. push ( start) ;
417419
418420 let goal = BitSet :: from_range ( 0 ..self . count ) ;
419421
420- while let Some ( ( d , state) ) = queue. pop ( ) {
422+ while let Some ( state) = queue. pop ( ) {
421423 if state. keys ( ) . contains_set ( & goal) {
422- return d ;
424+ return state . dist ( ) ;
423425 }
424426
425427 let c_dist = dist[ & state] ;
426- if d > c_dist {
428+ if state . dist ( ) > c_dist {
427429 continue ;
428430 }
429431
@@ -434,13 +436,14 @@ impl<const R: usize> KeyGraph<R> {
434436 . filter ( |& k| state. keys ( ) . contains_set ( & self . dependencies [ k] ) )
435437 {
436438 let weight = self . distances [ state. pos ( robot) ] [ n] ;
439+ let n_dist = c_dist + weight;
437440 let n_state = state
438441 . with_pos ( robot, n)
439- . with_key ( n, n != self . count ) ;
440- let n_dist = c_dist + weight ;
442+ . with_key ( n, n != self . count )
443+ . with_dist ( n_dist ) ;
441444
442445 if n_dist < dist. get ( & n_state) . copied ( ) . unwrap_or ( usize:: MAX ) {
443- queue. push ( n_dist , n_state) ;
446+ queue. push ( n_state) ;
444447 dist. insert ( n_state, n_dist) ;
445448 }
446449 }
0 commit comments