Track paths during distance calculation

This commit is contained in:
jazzpi 2022-12-21 19:54:27 +01:00
parent 95e4095f32
commit 49368e7985
2 changed files with 38 additions and 19 deletions

View File

@ -5,13 +5,13 @@ use aoc22::{
pub fn main() { pub fn main() {
let valves = day16::parse_valves(&util::parse_input()); let valves = day16::parse_valves(&util::parse_input());
let dists = day16::calc_dists(&valves); let paths = day16::calc_paths(&valves);
let state = day16::State::new(&valves); let state = day16::State::new(&valves, false);
let score = util::maximize(&state, &(&valves, &dists)); let score = util::maximize(&state, &(&valves, &paths));
println!( println!(
"Most pressure released is {}", "Most pressure released is {}",
score.lower_bound(&(&valves, &dists)) score.lower_bound(&(&valves, &paths))
); );
} }

View File

@ -56,21 +56,40 @@ pub fn parse_valves(input: &String) -> Vec<Valve> {
.collect() .collect()
} }
pub fn calc_dists(valves: &Vec<Valve>) -> Vec<Vec<usize>> { #[derive(Debug, Clone)]
pub struct Path {
pub dist: usize,
pub path: Vec<usize>,
}
pub fn calc_paths(valves: &Vec<Valve>) -> Vec<Vec<Path>> {
let n = valves.len(); let n = valves.len();
let mut result = vec![vec![usize::MAX; n]; n];
// result[from][to] = (dist, path)
let mut result = vec![
vec![
Path {
dist: usize::MAX,
path: Vec::new()
};
n
];
n
];
for i in 0..n { for i in 0..n {
result[i][i] = 0; result[i][i].dist = 0;
let mut next = VecDeque::new(); let mut next = VecDeque::new();
next.push_back(i); next.push_back(i);
while let Some(j) = next.pop_front() { while let Some(j) = next.pop_front() {
let d_next = result[i][j] + 1; let d_next = result[i][j].dist + 1;
for j in &valves[j].tunnels { for tunnel in &valves[j].tunnels {
let d_tunnel = result[i].get_mut(*j).unwrap(); let d_tunnel = &result[i][*tunnel];
if d_next < *d_tunnel { if d_next < d_tunnel.dist {
*d_tunnel = d_next; let mut path = result[i][j].path.clone();
next.push_back(*j); path.push(*tunnel);
result[i][*tunnel] = Path { dist: d_next, path };
next.push_back(*tunnel);
} }
} }
} }
@ -110,9 +129,9 @@ impl State {
} }
} }
type ExtraArgs<'a> = (&'a Vec<Valve>, &'a Vec<Vec<usize>>); type ExtraArgs<'a> = (&'a Vec<Valve>, &'a Vec<Vec<Path>>);
impl util::BnBState<ExtraArgs<'_>> for State { impl util::BnBState<ExtraArgs<'_>> for State {
fn possible_actions(&self, (valves, dists): &ExtraArgs) -> Vec<State> { fn possible_actions(&self, (valves, paths): &ExtraArgs) -> Vec<State> {
assert!(!self.finished()); assert!(!self.finished());
let mut result = Vec::new(); let mut result = Vec::new();
@ -132,7 +151,7 @@ impl util::BnBState<ExtraArgs<'_>> for State {
for l in &self.interesting { for l in &self.interesting {
let i = l.clone(); let i = l.clone();
let dist = dists[loc][i]; let dist = paths[loc][i].dist;
if dist == 0 || dist == usize::MAX || self.time_remaining < dist { if dist == 0 || dist == usize::MAX || self.time_remaining < dist {
continue; continue;
} }
@ -160,21 +179,21 @@ impl util::BnBState<ExtraArgs<'_>> for State {
self.pressure_released + self.flow_rate * self.time_remaining self.pressure_released + self.flow_rate * self.time_remaining
} }
fn upper_bound(&self, (valves, dists): &ExtraArgs) -> usize { fn upper_bound(&self, (valves, paths): &ExtraArgs) -> usize {
let mut additional_flow = 0; let mut additional_flow = 0;
for i in &self.interesting { for i in &self.interesting {
let i = i.clone(); let i = i.clone();
if (self.opened & (1 << i)) != 0 { if (self.opened & (1 << i)) != 0 {
continue; continue;
} }
let dist = dists[self.location][i]; let dist = paths[self.location][i].dist;
if dist < self.time_remaining { if dist < self.time_remaining {
let flow = valves[i].flow_rate; let flow = valves[i].flow_rate;
additional_flow += flow * (self.time_remaining - dist - 1); additional_flow += flow * (self.time_remaining - dist - 1);
} }
} }
self.lower_bound(&(valves, dists)) + additional_flow self.lower_bound(&(valves, paths)) + additional_flow
} }
} }