#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define FOR(i,n,m) for(int i=(int)(n); i<=(int)(m); i++)
#define RFOR(i,n,m) for(int i=(int)(n); i>=(int)(m); i--)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define RITR(x,c) for(__typeof(c.rbegin()) x=c.rbegin();x!=c.rend();x++)
#define setp(n) fixed << setprecision(n)

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }

#define ll long long
#define vll vector<ll>
#define vi vector<int>
#define pll pair<ll,ll>
#define pi pair<int,int>

#define all(a) (a.begin()),(a.end())
#define rall(a) (a.rbegin()),(a.rend())
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ins insert

using namespace std;

//-------------------------------------------------
//--Graph Template
//-------------------------------------------------
template<class E>
struct Graph
{
    vector<vector<E> > adj;
    Graph(int N):adj(N){}
    virtual void add_edge(int v, E e){adj[v].push_back(e);}
    vector<E>& operator[](int v){return adj[v];}
    inline int size(){return adj.size();}
};

struct Edge{int to; ll cost;};

//-------------------------------------------------
//--Dijkstra
//-------------------------------------------------
template<class T, class E>
vector<T> dijkstra(Graph<E> &G, int s, T inf)
{
    using P=pair<T,int>;
    vector<T> dist(G.size(),inf); dist[s]=0;
    priority_queue<P,vector<P>,greater<P> > que;
    que.push(P(0,s));
    while(!que.empty()){
        T cost; int v;
        tie(cost,v) = que.top(); que.pop();
        if (cost>dist[v]) continue;
        for(auto e:G[v]){
            if (dist[e.to]>dist[v]+e.cost){
                dist[e.to]=dist[v]+e.cost;
                que.push(P(dist[e.to],e.to));
            }
        }
    }
    return dist;
}

template<class T, class E>
vector<T> dijkstra_naive(Graph<E> &G, int s, T inf)
{
    int V = G.size();
    vector<T> dist(V,inf); dist[s]=0;
    vector<bool> use(V);
    while(true){
        int v=-1;
        for(int i=0;i<V;i++){
            if(!use[i] && (v==-1||dist[i]<dist[v])){
                v=i;
            }
        }
        if (v==-1) break;
        use[v]=true;
        for(auto e:G[v]){
            chmin(dist[e.to],dist[v]+e.cost);
        }
    }
    return dist;
}

bool isPal(const string &s)
{
    int N = s.size();
    rep(i,N/2){
        if (s[i]!=s[N-i-1]) return false;
    }
    return true;
}

bool isPrefix(const string &s, const string &t)
{
    int N = s.size();
    int M = t.size();
    if (N>M) return false;
    rep(i,N){
        if (s[i]!=t[i]) return false;
    }
    return true;
}

bool isSuffix(const string &s, const string &t)
{
    int N = s.size();
    int M = t.size();
    if (N>M) return false;
    rep(i,N){
        if (s[N-i-1]!=t[M-i-1]) return false;
    }
    return true;
}

const ll INF = 1e18;
const int MAX_V = 2002;
Graph<Edge> G(MAX_V);

//-------------------------------------------------

int main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N; cin>>N;
    vector<string> S(N);
    vll cost(N);
    rep(i,N) cin>>S[i]>>cost[i];
    auto T = S;
    rep(i,N) reverse(all(T[i]));

    int V=2;
    using P = pair<bool,string>;
    map<P,int> Map;
    Map[P(true,"")] = Map[P(false,"")] = 1;
    rep(i,N){
        int K = T[i].size();
        // Prefix
        rep(j,K){
            P t(false,T[i].substr(j));
            if (Map.count(t)){
                if (j==0) G.add_edge(0, {Map[t],cost[i]});
                continue;
            }
            Map[t] = V;
            if (j==0) G.add_edge(0, {V,cost[i]});
            if (isPal(t.se)) G.add_edge(V, {1,0});
            V++;
        }
        // Suffix
        rep(j,K){
            P t(true,T[i].substr(0,j+1));
            if (Map.count(t)){
                if (j==K-1) G.add_edge(0, {Map[t],cost[i]});
                continue;
            }
            Map[t] = V;
            if (j==K-1) G.add_edge(0, {V,cost[i]});
            if (isPal(t.se)) G.add_edge(V, {1,0});
            V++;
        }
    }
    for(auto p:Map){
        P s = p.fi;
        int v = p.se;
        if (s.fi){
            rep(i,N){
                int next;
                if (isSuffix(S[i],s.se)){
                    int sz = s.se.size()-S[i].size();
                    next = Map[P(true,s.se.substr(0,sz))];
                }else if(isSuffix(s.se,S[i])){
                    int sz = S[i].size()-s.se.size();
                    string tmp = S[i].substr(0,sz);
                    reverse(all(tmp));
                    next = Map[P(false,tmp)];
                }else{
                    continue;
                }
                G.add_edge(v,{next,cost[i]});
            }
        }else{
            rep(i,N){
                int next;
                if (isPrefix(S[i],s.se)){
                    int sz = S[i].size();
                    next = Map[P(false,s.se.substr(sz))];
                }else if(isPrefix(s.se,S[i])){
                    int sz = s.se.size();
                    string tmp = S[i].substr(sz);
                    reverse(all(tmp));
                    next = Map[P(true,tmp)];
                }else{
                    continue;
                }
                G.add_edge(v,{next,cost[i]});
            }
        }
    }
    auto dist = dijkstra(G,0,INF);
    cout<<(dist[1]==INF?-1:dist[1])<<endl;
    return 0;
}


Measured memory_bytes: 3896