1
- use std:: cmp:: max;
1
+ use std:: cmp:: { max, min } ;
2
2
use std:: collections:: { HashMap , HashSet } ;
3
3
use std:: str:: FromStr ;
4
4
use anyhow:: { anyhow, Result , Error } ;
@@ -19,8 +19,8 @@ pub fn parsing(lines: &Vec<String>) -> (HashMap<String, Vec<String>>, HashMap<St
19
19
}
20
20
21
21
22
- fn dfs (
23
- best_records : & mut HashMap < ( String , usize ) , usize > ,
22
+ fn dfs_1 (
23
+ best_records : & mut HashMap < ( String , bool , usize ) , usize > ,
24
24
mins_left : usize ,
25
25
pos : String ,
26
26
mut opened_valves : HashSet < String > ,
@@ -30,13 +30,20 @@ fn dfs(
30
30
valve_flow_rate_mapping : & HashMap < String , usize > ,
31
31
num_valves_with_flow : usize ,
32
32
) {
33
- let record = best_records . entry ( ( pos . clone ( ) , mins_left ) ) . or_insert ( pressure_released ) ;
34
- if * record <= pressure_released {
35
- * record = pressure_released ;
33
+ let mut cur_pos_opened ;
34
+ if opened_valves . contains ( & pos ) {
35
+ cur_pos_opened = true ;
36
36
}
37
37
else {
38
+ cur_pos_opened = false ;
39
+ }
40
+ if best_records. contains_key ( & ( pos. clone ( ) , cur_pos_opened, mins_left) ) && best_records[ & ( pos. clone ( ) , cur_pos_opened, mins_left) ] >= pressure_released {
38
41
return ;
39
42
}
43
+ else {
44
+ best_records. insert ( ( pos. clone ( ) , cur_pos_opened, mins_left) , pressure_released) ;
45
+ }
46
+
40
47
if mins_left == 0 || mins_left - 1 == 0 {
41
48
pressure_records. push ( pressure_released) ;
42
49
return
@@ -47,25 +54,115 @@ fn dfs(
47
54
}
48
55
49
56
for neighbor in & valves_connection_mapping[ & pos] {
50
- dfs ( best_records, mins_left-1 , neighbor. to_owned ( ) , opened_valves. clone ( ) , pressure_records, pressure_released, valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
57
+ dfs_1 ( best_records, mins_left-1 , neighbor. to_owned ( ) , opened_valves. clone ( ) , pressure_records, pressure_released, valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
51
58
}
52
59
53
- if valve_flow_rate_mapping[ & pos] == 0 {
60
+ if valve_flow_rate_mapping[ & pos] == 0 || opened_valves . contains ( & pos ) {
54
61
return ;
55
62
}
63
+ opened_valves. insert ( pos. clone ( ) ) ;
64
+ dfs_1 ( best_records, mins_left-1 , pos. to_owned ( ) , opened_valves. clone ( ) , pressure_records, pressure_released + valve_flow_rate_mapping[ & pos] * ( mins_left-1 ) , valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
65
+ }
66
+
67
+ pub fn part_1 ( valves_connection_mapping : & HashMap < String , Vec < String > > , valve_flow_rate_mapping : & HashMap < String , usize > ) -> usize {
68
+ let num_valves_with_flow = valve_flow_rate_mapping
69
+ . values ( )
70
+ . map ( |x| {
71
+ if * x > 0 {
72
+ 1
73
+ }
74
+ else {
75
+ 0
76
+ }
77
+ } )
78
+ . sum ( ) ;
79
+ let mut pressure_records = vec ! [ ] ;
80
+ let mut best_records = HashMap :: new ( ) ;
81
+ dfs_1 ( & mut best_records, MINUTES , "AA" . to_owned ( ) , HashSet :: new ( ) , & mut pressure_records, 0 , valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
82
+ pressure_records. into_iter ( ) . max ( ) . unwrap ( )
83
+ }
84
+
85
+ fn dfs_2 (
86
+ best_records : & mut HashMap < ( String , String , bool , bool , usize ) , usize > ,
87
+ mins_left : usize ,
88
+ pos : String ,
89
+ epos : String , // elephant pos
90
+ mut opened_valves : HashSet < String > ,
91
+ pressure_records : & mut Vec < usize > ,
92
+ pressure_released : usize ,
93
+ valves_connection_mapping : & HashMap < String , Vec < String > > ,
94
+ valve_flow_rate_mapping : & HashMap < String , usize > ,
95
+ num_valves_with_flow : usize ,
96
+ ) {
97
+ let mut cur_pos_opened;
56
98
if opened_valves. contains ( & pos) {
99
+ cur_pos_opened = true ;
100
+ }
101
+ else {
102
+ cur_pos_opened = false ;
103
+ }
104
+ let mut cur_epos_opened;
105
+ if opened_valves. contains ( & epos) {
106
+ cur_epos_opened = true ;
107
+ }
108
+ else {
109
+ cur_epos_opened = false ;
110
+ }
111
+ // if released pressure is lower than the same positions at the same time, no need to continue on this path
112
+ if best_records. contains_key ( & ( pos. clone ( ) , epos. clone ( ) , cur_pos_opened, cur_epos_opened, mins_left) ) && best_records[ & ( pos. clone ( ) , epos. clone ( ) , cur_pos_opened, cur_epos_opened, mins_left) ] >= pressure_released {
57
113
return ;
58
114
}
59
115
else {
60
- opened_valves. insert ( pos. clone ( ) ) ;
116
+ // pos and epos are mirrored
117
+ best_records. insert ( ( pos. clone ( ) , epos. clone ( ) , cur_pos_opened, cur_epos_opened, mins_left) , pressure_released) ;
118
+ best_records. insert ( ( epos. clone ( ) , pos. to_owned ( ) , cur_epos_opened, cur_pos_opened, mins_left) , pressure_released) ;
119
+ }
120
+ // not enough time to make a diff
121
+ if mins_left <= 1 {
122
+ pressure_records. push ( pressure_released) ;
123
+ return
124
+ }
125
+ // all valves which can release pressure have been opened
126
+ if opened_valves. len ( ) == num_valves_with_flow {
127
+ pressure_records. push ( pressure_released) ;
128
+ return
61
129
}
62
130
131
+ // if neither choose to open valves
63
132
for neighbor in & valves_connection_mapping[ & pos] {
64
- dfs ( best_records, mins_left-2 , neighbor. to_owned ( ) , opened_valves. clone ( ) , pressure_records, pressure_released + valve_flow_rate_mapping[ & pos] * ( mins_left-1 ) , valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
133
+ for e_neighbor in & valves_connection_mapping[ & epos] {
134
+ dfs_2 ( best_records, mins_left - 1 , neighbor. to_owned ( ) , e_neighbor. to_owned ( ) , opened_valves. clone ( ) , pressure_records, pressure_released, valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
135
+ }
65
136
}
66
- }
67
137
68
- pub fn part_1 ( valves_connection_mapping : & HashMap < String , Vec < String > > , valve_flow_rate_mapping : & HashMap < String , usize > ) -> usize {
138
+ // if only one choose to open valves
139
+ let mut pos_opened_just_now = false ;
140
+ if valve_flow_rate_mapping[ & pos] != 0 && !opened_valves. contains ( & pos) {
141
+ let mut opened_valves_clone = opened_valves. clone ( ) ;
142
+ opened_valves_clone. insert ( pos. clone ( ) ) ;
143
+ pos_opened_just_now = true ;
144
+ for e_neighbor in & valves_connection_mapping[ & epos] {
145
+ dfs_2 ( best_records, mins_left - 1 , pos. to_owned ( ) , e_neighbor. to_owned ( ) , opened_valves_clone. clone ( ) , pressure_records, pressure_released + valve_flow_rate_mapping[ & pos] * ( mins_left-1 ) , valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
146
+ }
147
+ }
148
+ let mut epos_opened_just_now = false ;
149
+ if valve_flow_rate_mapping[ & epos] != 0 && !opened_valves. contains ( & epos) {
150
+ let mut opened_valves_clone = opened_valves. clone ( ) ;
151
+ opened_valves_clone. insert ( epos. clone ( ) ) ;
152
+ epos_opened_just_now = true ;
153
+ for neighbor in & valves_connection_mapping[ & pos] {
154
+ dfs_2 ( best_records, mins_left - 1 , neighbor. to_owned ( ) , epos. to_owned ( ) , opened_valves_clone. clone ( ) , pressure_records, pressure_released + valve_flow_rate_mapping[ & epos] * ( mins_left-1 ) , valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
155
+ }
156
+ }
157
+ // if both choose to open valves
158
+ if pos != epos && pos_opened_just_now && epos_opened_just_now {
159
+ opened_valves. insert ( epos. clone ( ) ) ;
160
+ opened_valves. insert ( pos. clone ( ) ) ;
161
+ dfs_2 ( best_records, mins_left - 1 , pos. to_owned ( ) , epos. clone ( ) , opened_valves. clone ( ) , pressure_records, pressure_released + valve_flow_rate_mapping[ & pos] * ( mins_left-1 ) + valve_flow_rate_mapping[ & epos] * ( mins_left-1 ) , valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
162
+ }
163
+ }
164
+
165
+ pub fn part_2 ( valves_connection_mapping : & HashMap < String , Vec < String > > , valve_flow_rate_mapping : & HashMap < String , usize > ) -> usize {
69
166
let num_valves_with_flow = valve_flow_rate_mapping
70
167
. values ( )
71
168
. map ( |x| {
@@ -79,9 +176,6 @@ pub fn part_1(valves_connection_mapping: &HashMap<String, Vec<String>>, valve_fl
79
176
. sum ( ) ;
80
177
let mut pressure_records = vec ! [ ] ;
81
178
let mut best_records = HashMap :: new ( ) ;
82
- dfs ( & mut best_records, MINUTES , "AA" . to_owned ( ) , HashSet :: new ( ) , & mut pressure_records, 0 , valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
179
+ dfs_2 ( & mut best_records, MINUTES - 4 , "AA" . to_owned ( ) , "AA" . to_owned ( ) , HashSet :: new ( ) , & mut pressure_records, 0 , valves_connection_mapping, valve_flow_rate_mapping, num_valves_with_flow) ;
83
180
pressure_records. into_iter ( ) . max ( ) . unwrap ( )
84
- }
85
- pub fn part_2 ( valves_connection_mapping : HashMap < String , Vec < String > > , valve_flow_rate_mapping : HashMap < String , usize > ) -> usize {
86
- 0
87
- }
181
+ }
0 commit comments