Track paths during distance calculation
This commit is contained in:
parent
95e4095f32
commit
49368e7985
@ -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))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
49
src/day16.rs
49
src/day16.rs
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user