use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::Sub;
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::BTreeSet;
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer
}
fn read_lines<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
fn read_tabulate<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split(' ').map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read {
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum Dir {
    Up, Right, Down, Left
}
impl Dir {
    fn to_int(&self) -> i32 {
        match *self {
            Dir::Up => 0,
            Dir::Right => 1,
            Dir::Down => 2,
            Dir::Left => 3
        }
    }
    fn from_int(value: i32) -> Dir {
        match value & 3 {
            0 => Dir::Up,
            1 => Dir::Right,
            2 => Dir::Down,
            3 => Dir::Left,
            _ => panic!()
        }
    }
    fn reverse(&self) -> Dir {
        Dir::from_int(self.to_int() + 2)
    }
    fn to_coordinate(&self) -> Coordinate {
        match *self {
            Dir::Up => Coordinate{x: 0, y: -1},
            Dir::Right => Coordinate{x: 1, y: 0},
            Dir::Down => Coordinate{x: 0, y: 1},
            Dir::Left => Coordinate{x: -1, y: 0}
        }
    }
    fn all() -> Vec<Dir> {
        vec![Dir::Up, Dir::Right, Dir::Down, Dir::Left]
    }
    
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
struct Coordinate {
    x: i32, y: i32
}
impl Coordinate {
}
impl Add for Coordinate {
    type Output = Coordinate;
    fn add(self, rhs: Coordinate) -> <Self as std::ops::Add<Coordinate>>::Output { 
        Coordinate{x: self.x + rhs.x, y: self.y + rhs.y}
     }
}

fn read_initial_state(state: &Vec<Vec<char>>) -> (Coordinate, i32) {
    let mut current_pos = (0 .. state.len()).into_iter().flat_map(|y| (0 .. state[y].len()).into_iter().find(|&x| state[y][x] == 'e').map(|x| Coordinate{x: x as i32, y: y as i32})).into_iter().next().unwrap();
    let mut serial = 0i32;
    for c in "dcbaS".chars() {
        for dir in Dir::all() {
            let Coordinate{x: x, y: y} = dir.to_coordinate() + current_pos;
            if 0 <= y && y < state.len() as i32 && 0 <= x && x < state[y as usize].len() as i32 && state[y as usize][x as usize] == c {
                current_pos = Coordinate{x: x, y: y};
                serial <<= 2;
                serial += dir.to_int();
                break;
            }
        }
    }
    (current_pos, serial)
}
fn can_move_to(dir: Dir, mut head: Coordinate, mut serial: i32) -> bool {
    let next = dir.to_coordinate() + head;
    for _ in 0 .. 4 {
        head = head + Dir::from_int(serial & 3).reverse().to_coordinate();
        if next == head {
            return false;
        }        
        serial >>= 2;
    }
    true
}
fn main() {
    read!{
        height: usize, width: usize, n: usize
    }
    read! {
        state: [String; height]
    }
    let state = state.into_iter().map(|str| str.chars().collect::<Vec<_>>()).collect::<Vec<_>>();
    let mut min_step = vec![vec![vec![vec![std::usize::MAX; n + 1]; 1 << 10]; width]; height];
    let mut queue = VecDeque::new();
    let (initial_pos, initial_state) = read_initial_state(&state);
    let mask = 1023;
    queue.push_back((initial_pos, initial_state, 0));
    min_step[initial_pos.y as usize][initial_pos.x as usize][initial_state as usize][0] = 0;
    while let Some((pos, serial, count)) = queue.pop_front() {
        let step = min_step[pos.y as usize][pos.x as usize][serial as usize][count];
        for dir in Dir::all() {
            let Coordinate{x: x, y: y} = pos + dir.to_coordinate();
            if 0 <= y && y < state.len() as i32 && 0 <= x && x < state[y as usize].len() as i32 && can_move_to(dir, pos, serial) {
                match state[y as usize][x as usize] {
                    '#' => continue,
                    c => {
                        let new_serial = ((serial << 2) + dir.to_int()) & mask;
                        let num = if '0' < c && c <= '9' && c as i32 - '0' as i32 == count as i32 + 1 {
                            count + 1
                        }else {
                            count
                        };
                        if min_step[y as usize][x as usize][new_serial as usize][num as usize] == std::usize::MAX {
                            min_step[y as usize][x as usize][new_serial as usize][num as usize] = step + 1;
                            queue.push_back((Coordinate{x: x, y: y}, new_serial, num));
                        } 
                    }
                }
            }
        }
    }
    let mut result = std::usize::MAX;
    for i in 0 .. height {
        for j in 0 .. width {
            for s in 0 .. 1024 {
                result = min(result, min_step[i][j][s][n]);
            }
        }
    }
    if result == std::usize::MAX {
        println!("-1");
    }else {
        println!("{}", result);
    }
    
}



Measured memory_bytes: 15288