use std::io::{self, Read}; fn try_push( next: usize, dist_next: i32, blocked: &[u8], dist: &mut [i32], queue: &mut Vec, ) { if blocked[next] == 0 && dist[next] == -1 { dist[next] = dist_next; queue.push(next as u32); } } fn main() { let mut input = String::new(); io::stdin().read_to_string(&mut input).unwrap(); let mut it = input.split_whitespace(); let h: usize = it.next().unwrap().parse().unwrap(); let w: usize = it.next().unwrap().parse().unwrap(); let hh = 2 * h - 1; let ww = 2 * w - 1; let total = hh * ww; let mut blocked = vec![0_u8; total]; for i in 0..h { let row = it.next().unwrap().as_bytes().to_vec(); for j in 0..w { if row[j] == b'#' { blocked[(2 * i) * ww + 2 * j] = 1; } } } let goal = total - 1; let mut dist = vec![-1_i32; total]; let mut queue = Vec::with_capacity(total.min(1_000_000)); dist[0] = 0; queue.push(0); let mut head = 0_usize; while head < queue.len() { let v = queue[head] as usize; head += 1; if v == goal { break; } let x = v / ww; let y = v - x * ww; let nd = dist[v] + 1; if x > 0 { try_push(v - ww, nd, &blocked, &mut dist, &mut queue); } if x + 1 < hh { try_push(v + ww, nd, &blocked, &mut dist, &mut queue); } if y > 0 { try_push(v - 1, nd, &blocked, &mut dist, &mut queue); } if y + 1 < ww { try_push(v + 1, nd, &blocked, &mut dist, &mut queue); } if x % 2 == 0 { if x >= 2 { try_push(v - 2 * ww, nd, &blocked, &mut dist, &mut queue); } if x + 2 < hh { try_push(v + 2 * ww, nd, &blocked, &mut dist, &mut queue); } } if y % 2 == 0 { if y >= 2 { try_push(v - 2, nd, &blocked, &mut dist, &mut queue); } if y + 2 < ww { try_push(v + 2, nd, &blocked, &mut dist, &mut queue); } } } println!("{}", dist[goal]); }