#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;

#define sz(x) (int)((x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define endl '\n'
#define x first
#define y second
#define int long long
#define double long double
#define pii pair<int, int>
#define pb push_back
#define vec vector
#define beg begin
#define dbg(x) cerr << #x << " = " << x << endl;

template<class T> ostream& operator<<(ostream &str, vector<T> &a) {
    for (auto &i : a) {
        str << i << " ";
    }
    return str;
}

template<class T> istream& operator>>(istream &str, vector<T> &a) {
    for (auto &i : a) {
        str >> i;
    }
    return str;
}

template<class T> ostream& operator<<(ostream &str, pair<T, T> &a) {
    str << a.first << " " << a.second;
    return str;
}

template<class T> istream& operator>>(istream &str, pair<T, T> &a) {
    str >> a.first >> a.second;
    return str;
}

void solve(); signed main() {
#ifdef LOCAL
    freopen("C:\\Users\\artma\\CLionProjects\\problems\\input.txt", "r", stdin);
#endif
    srand(time(0));
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cout.setf(ios::fixed); cout.precision(6);
    solve();
    return 0;
}

const int MOD = 1e9 + 7, MAXN = 1e6 + 10, INF = 1e18 + 10, BASE = 37;

bool is_pol(string &s) {
    bool ok = true;
    for (int i = 0; i < sz(s) / 2; ++i) {
        if (s[i] != s[sz(s) - i - 1]) {
            ok = false;
            break;
        }
    }
    return ok;
}

void solve() {
    int n;
    cin >> n;
    vec<string> s(n);
    vec<int> c(n);
    for (int i = 0; i < n; ++i) {
        cin >> s[i] >> c[i];
    }
    map<string, int> cost;
    for (auto it : s) {
        cost[it] = INF;
    }
    for (int i = 0; i < n; ++i) {
        cost[s[i]] = min(c[i], cost[s[i]]);
    }

    vec<pair<string, string>> vertex;
    vertex.pb({"", ""});
    for (auto it : s) {
        for (int i = 0; i < sz(it); ++i) {
            vertex.pb({"", it.substr(0, i + 1)});
            vertex.pb({it.substr(sz(it) - i - 1, i + 1), ""});
        }
    }
    sort(all(vertex));
    vertex.resize(unique(all(vertex)) - vertex.beg());

    int ans = INF;
    for (auto start : vertex) {
        if (cost[start.x] == 0 && cost[start.y] == 0) continue;
        set<pair<int, pair<string, string>>> se;
        map<pair<string, string>, int> dist;
        for (auto v : vertex) {
            dist[v] = INF;
        }
        dist[start] = cost[start.x] + cost[start.y];
        se.insert({dist[start], start});
        while (!se.empty()) {
            auto cur = *se.begin();
            se.erase(cur);
            vec<pair<int, pair<string, string>>> nxt; // {стоимость сделать такое состояние, состояние_nxt}
            auto p = cur.y;
            for (auto it : s) {
                if (p.x == "") {
                    string tr = p.y;
                    string tl = it;
                    if (sz(tl) <= sz(tr)) {
                        reverse(all(tl));
                        bool ok = true;
                        for (int i = 0; i < sz(tl); ++i) {
                            if (tl[sz(tl) - i - 1] != tr[sz(tr) - i - 1]) {
                                ok = false;
                                break;
                            }
                        }
                        if (ok) {
                            string tmp;
                            for (int i = 0; i < sz(tr) - sz(tl); ++i) {
                                tmp.pb(tr[i]);
                            }
                            assert(sz(tmp) == sz(tr) - sz(tl));
                            nxt.pb({cost[it], {"", tmp}});
                        }
                    }
                    else {
                        bool ok = true;
                        reverse(all(tr));
                        for (int i = 0; i < sz(tr); ++i) {
                            if (tl[i] != tr[i]) {
                                ok = false;
                                break;
                            }
                        }
                        if (ok) {
                            string tmp;
                            for (int i = sz(tr); i < sz(tl); ++i) {
                                tmp.pb(tl[i]);
                            }
                            assert(sz(tmp) == sz(tl) - sz(tr));
                            nxt.pb({cost[it], {tmp, ""}});
                        }
                    }
                }
                else {
                    string tl = p.x;
                    string tr = it;
                    if (sz(tl) <= sz(tr)) {
                        reverse(all(tl));
                        bool ok = true;
                        for (int i = 0; i < sz(tl); ++i) {
                            if (tl[sz(tl) - i - 1] != tr[sz(tr) - i - 1]) {
                                ok = false;
                                break;
                            }
                        }
                        if (ok) {
                            string tmp;
                            for (int i = 0; i < sz(tr) - sz(tl); ++i) {
                                tmp.pb(tr[i]);
                            }
                            assert(sz(tmp) == sz(tr) - sz(tl));
                            nxt.pb({cost[it], {"", tmp}});
                        }
                    }
                    else {
                        bool ok = true;
                        reverse(all(tr));
                        for (int i = 0; i < sz(tr); ++i) {
                            if (tl[i] != tr[i]) {
                                ok = false;
                                break;
                            }
                        }
                        if (ok) {
                            string tmp;
                            for (int i = sz(tr); i < sz(tl); ++i) {
                                tmp.pb(tl[i]);
                            }
                            assert(sz(tmp) == sz(tl) - sz(tr));
                            nxt.pb({cost[it], {tmp, ""}});
                        }
                    }
                }
            }
            for (auto v : nxt) {
                if (dist[v.y] > dist[cur.y] + v.x) {
                    se.erase({dist[v.y], v.y});
                    dist[v.y] = dist[cur.y] + v.x;
                    se.insert({dist[v.y], v.y});
                }
            }
        }

        for (auto v : vertex) {
            if (is_pol(v.x) && is_pol(v.y)) {
                ans = min(ans, dist[v]);
            }
        }
    }

    if (ans == INF) {
        cout << -1 << endl;
    }
    else {
        cout << ans << endl;
    }
}

Measured memory_bytes: 4228