#![allow(unused_imports)]
#![allow(unused_macros)]
use std::cmp::{max, min};
use std::collections::*;
use std::io::{stdin, Read};

#[allow(unused_macros)]
macro_rules! parse {
    ($it: ident ) => {};
    ($it: ident, ) => {};
    ($it: ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
    ($it: ident, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
    ($it: ident, $var:ident $($r:tt)*) => {
        let $var = parse_val!($it, usize);
        parse!($it $($r)*);
    };
}

#[allow(unused_macros)]
macro_rules! parse_val {
    ($it: ident, [$t:tt; $len:expr]) => {
        (0..$len).map(|_| parse_val!($it, $t)).collect::<Vec<_>>();
    };
    ($it: ident, ($($t: tt),*)) => {
        ($(parse_val!($it, $t)),*)
    };
    ($it: ident, u1) => {
        $it.next().unwrap().parse::<usize>().unwrap() -1
    };
    ($it: ident, $t: ty) => {
        $it.next().unwrap().parse::<$t>().unwrap()
    };
}

#[cfg(debug_assertions)]
macro_rules! debug {
    ($( $args:expr ),*) => { eprintln!( $( $args ),* ); }
}

#[cfg(not(debug_assertions))]
macro_rules! debug {
    ($( $args:expr ),*) => {
        ()
    };
}

const M: usize = std::usize::MAX / 10;
fn search<'a>(
    s: &'a [String],
    t: &'a [String],
    n: usize,
    direction: bool,
    curs: &'a str,
    cost: usize,
    c: &[usize],
    seen: &mut HashMap<(bool, &'a str), usize>,
) -> usize {
    let k = (direction, curs);
    if seen.contains_key(&k) && cost >= seen[&k] {
        return M;
    }
    seen.insert(k, cost);
    let mut ret = M;
    for i in 0..n {
        let target = if direction { &t[i] } else { &s[i] };
        let (ns, direction) = if target.starts_with(&curs) {
            (&target[curs.len()..], !direction)
        } else if curs.starts_with(target) {
            (&curs[target.len()..], direction)
        } else {
            continue;
        };
        if ns == ns.chars().rev().collect::<String>() {
            ret = min(ret, cost + c[i]);
        } else if ns.len() < 2 {
            ret = min(ret, cost + c[i]);
        } else {
            ret = min(ret, search(s, t, n, direction, ns, cost + c[i], c, seen));
        }
    }
    ret
}

fn solve(s: &str) {
    let mut it = s.split_whitespace();
    parse!(it, n: usize);
    let mut s = vec![];
    let mut c = vec![];
    for _ in 0..n {
        s.push(it.next().unwrap().to_string());
        parse!(it, c_: usize);
        c.push(c_);
    }
    let t: Vec<_> = s
        .iter()
        .map(|x| x.chars().rev().collect::<String>())
        .collect();
    let mut ret = M;
    for i in 0..n {
        let curs = &s[i];
        let mut seen = HashMap::new();
        ret = min(ret, search(&s, &t, n, true, curs, c[i], &c, &mut seen));
        if s[i] == t[i] {
            ret = min(ret, c[i]);
        }
    }

    if ret == M {
        println!("{}", -1);
    } else {
        println!("{}", ret);
    }
}

fn main() {
    let mut s = String::new();
    stdin().read_to_string(&mut s).unwrap();
    solve(&s);
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_input() {
        let s = "
        ";
        solve(s);
    }
}


Measured memory_bytes: 2200