#include<bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define eb emplace_back
#define all(a) (a).begin(),(a).end()
#define SZ(a) (int)(a).size()
#define FOR(i, a, b) for(int i=(a); i<=(b); ++i)
#define ROF(i, a, b) for(int i=(a); i>=(b); --i)
#define make_unique(a) sort(all((a))), (a).resize(unique(all((a)))-(a).begin())

using namespace std;

typedef pair<int,int> PII;
typedef long long LL;
typedef double DD;
typedef long double LD;
typedef pair<LL,LL> PLL;
typedef pair<DD,DD> PDD;
typedef vector<int> VI;
typedef vector<LL> VL;

const int N = 52, L = 44;
struct A{
    LL cost;
    int st, idx;
    bool operator < (const A& o) const{
        return cost > o.cost;
    }
};
vector<A> g[2][N*L];
vector<string> dict, word;
LL dp[2][N*L], cost[N];
int search(string x){
    return lower_bound(all(dict), x)-dict.begin();
}
void solve(){
    int n;
    cin >> n;
    word.resize(n+1);
    FOR(i, 1, n){
        cin >> word[i] >> cost[i];
        int l = word[i].length();
        FOR(j, 0, l-1){
            dict.pb(word[i].substr(0,j+1));
            dict.pb(word[i].substr(j));
        }
    }
    dict.pb("");
    make_unique(dict);
    LL inf = 1e18;
    int m = SZ(dict);
    FOR(i, 0, m-1){
        //printf("%d : %s\n",i,dict[i].c_str());
        dp[0][i] = dp[1][i] = inf;
        int l = dict[i].length();
        // check if itself is palindrome
        bool chek = true;
        FOR(j, 0, l/2-1){
            if(dict[i][j] != dict[i][l-1-j]){
                chek = false; break;
            }
        }
        if(chek){
            // this is already palindrome
            //cout << "kono palindrome da!" << endl;
            dp[0][i] = dp[1][i] = 0;
            continue;
        }
        // adding suffix
        FOR(j, 1, n){
            bool ch = true;
            int ll = word[j].length();
            FOR(k, 0, min(l-1, ll-1)){
                if(dict[i][k] != word[j][ll-1-k]){
                    ch = false; break;
                }
            }
            if(!ch) continue;
            if(l == ll) g[0][0].pb({cost[j],0,i});
            if(l < ll){
                int idx = search(word[j].substr(0,ll-l));
                g[1][idx].pb({cost[j],0,i});
            }
            if(l > ll){
                int idx = search(dict[i].substr(ll));
                g[0][idx].pb({cost[j],0,i});
            }
        }
        // adding prefix
        FOR(j, 1, n){
            bool ch = true;
            int ll = word[j].length();
            FOR(k, 0, min(l-1, ll-1)){
                if(word[j][k] != dict[i][l-1-k]){
                    ch = false; break;
                }
            }
            if(!ch) continue;
            if(l == ll) g[0][0].pb({cost[j],1,i});
            if(ll < l){
                int idx = search(dict[i].substr(0,l-ll));
                g[1][idx].pb({cost[j],1,i});
            }
            if(ll > l){
                int idx = search(word[j].substr(l));
                g[0][idx].pb({cost[j],1,i});
            }
        }
    }
    // dijk
    priority_queue<A> dijk;
    FOR(i, 0, m-1){
        FOR(j, 0, 1){
            if(dp[j][i] != inf){
                dijk.push({dp[j][i], j, i});
            }
        }
    }
    while(!dijk.empty()){
        LL cost = dijk.top().cost;
        int st = dijk.top().st;
        int idx = dijk.top().idx;
        dijk.pop();
        if(cost != dp[st][idx]) continue;
        for(A e : g[st][idx]){
            if(dp[e.st][e.idx] > cost + e.cost){
                dp[e.st][e.idx] = cost + e.cost;
                dijk.push({dp[e.st][e.idx], e.st, e.idx});
            }
        }
    }
    // brute
    LL ans = inf;
    bool found = false;
    FOR(i, 1, n){
        int idx = search(word[i]);
        FOR(j, 0, 1){
            if(dp[j][idx] != inf){
                found = true;
                ans = min(ans, dp[j][idx]+cost[i]);
            }
        }
    }
    if(found) cout << ans;
    else cout << -1;
}

int main(){
    solve();
	return 0;
}
/*
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

Measured memory_bytes: 3884