//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define rep(i, n) for(int i=0; i<n; ++i)
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
using namespace std;
using ll = int64_t;
using ld = long double;
using P = pair<int, int>;
using vs = vector<string>;
using vi = vector<int>;
using vvi = vector<vi>;
template<class T> using PQ = priority_queue<T>;
template<class T> using PQG = priority_queue<T, vector<T>, greater<T> >;
const int INF = 100010001;
const ll LINF = (ll)INF*INF*10;
template<typename T1, typename T2>
inline bool chmax(T1 &a, T2 b) {return a < b && (a = b, true);}
template<typename T1, typename T2>
inline bool chmin(T1 &a, T2 b) {return a > b && (a = b, true);}
template<typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) { return is >> p.first >> p.second;}
template<typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) { return os << p.first << ' ' << p.second;}

struct edge {
  int to;
  int64_t cost;
  edge(int x=0, int64_t y=0):to(x), cost(y) {}
};

vector<vector<edge> > G; // resizeの必要あり

struct dijkstra {
  vector<int64_t> d;
  dijkstra(int s, int n):d(n, INT64_MAX/3) { // sはスタート,nは頂点数
    d[s] = 0LL;
    priority_queue<pair<int64_t, int>, vector<pair<int64_t, int> >, greater<pair<int64_t, int> > > que;
    que.push(make_pair(0LL, s));
    while(!que.empty()) {
      pair<int64_t, int> now = que.top();
      que.pop();
      if(now.first != d[now.second]) continue;
      for(edge next:G[now.second]) {
        if(d[next.to] > d[now.second] + next.cost) {
          d[next.to] = d[now.second] + next.cost;
          que.push(make_pair(d[next.to], next.to));
        }
      }
    }
  }
  int64_t &operator[](int idx) {return d[idx];}
  const int64_t &operator[](int idx) const {return d[idx];}
};

const int N = 55;

//head

int n;
string s[N];
int c[N];
vs info1, info2;


int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n;
  rep(i, n) cin >> s[i] >> c[i];

  rep(i, n) {
    rep(j, s[i].size()) {
      info2.emplace_back(s[i].substr(j));
      info1.emplace_back(s[i].substr(0, j+1));
    }
  }
  sort(all(info1));
  sort(all(info2));
  info1.erase(unique(all(info1)), info1.end());
  info2.erase(unique(all(info2)), info2.end());

  const int ichi = info1.size(), ni = info2.size();

  G.resize(ichi + ni + 2);
  const int t = ichi + ni, ss = ichi + ni + 1;
  rep(i, n) {
    int siz = s[i].size();
    G[ss].emplace_back(lower_bound(all(info1), s[i])-info1.begin(), c[i]);
    G[ss].emplace_back(lower_bound(all(info2), s[i])-info2.begin() + ichi, c[i]);
    string x = s[i];
    reverse(all(x));
    int num = lower_bound(all(info1), x) - info1.begin();
    if(num != ichi and info1[num] == x) G[num].emplace_back(t, c[i]);
    num = lower_bound(all(info2), x) - info2.begin() + ichi;
    if(num != ichi + ni and info2[num-ichi] == x) G[num].emplace_back(t, c[i]);
    rep(j, siz-1) {
      string a = s[i].substr(0, j+1);
      string b = s[i].substr(j+1);
      reverse(all(a));
      if(a.size() > b.size()) {
        if(a.substr(0, b.size()) == b) {
          string h = a.substr(b.size());
          reverse(all(h));
          int num = lower_bound(all(info1), h) - info1.begin();
          G[ss].emplace_back(num, c[i]);
        }
      }
      else if(a.size() < b.size()) {
        if(a == b.substr(0, a.size())) {
          int num = lower_bound(all(info2), b.substr(a.size())) - info2.begin();
          G[ss].emplace_back(ichi + num, c[i]);
        }
      }
      else {
        if(a == b) G[ss].emplace_back(t, c[i]);
      }
    }
    rep(j, siz) {
      string a = s[i].substr(0, j);
      string b = s[i].substr(j+1);
      reverse(all(a));
      if(a.size() > b.size()) {
        if(a.substr(0, b.size()) == b) {
          string h = a.substr(b.size());
          reverse(all(h));
          int num = lower_bound(all(info1), h) - info1.begin();
          G[ss].emplace_back(num, c[i]);
        }
      }
      else if(a.size() < b.size()) {
        if(a == b.substr(0, a.size())) {
          int num = lower_bound(all(info2), b.substr(a.size())) - info2.begin();
          G[ss].emplace_back(ichi + num, c[i]);
        }
      }
      else {
        if(a == b) G[ss].emplace_back(t, c[i]);
      }
    }
    rep(j, ichi) {
      string J = info1[j];
      if(J.size() > siz) {
        reverse(all(J));
        if(J.substr(0, siz) == s[i]) {
          J = J.substr(siz);
          reverse(all(J));
          num = lower_bound(all(info1), J) - info1.begin();
          G[j].emplace_back(num, c[i]);
        }
      }
      else if(J.size() < siz) {
        reverse(all(J));
        if(J == s[i].substr(0, J.size())) {
          J = s[i].substr(J.size());
          num = lower_bound(all(info2), J) - info2.begin() + ichi;
          G[j].emplace_back(num, c[i]);
        }
      }
    }
    rep(j, ni) {
      string J = info2[j];
      if(J.size() > siz) {
        reverse(all(J));
        if(J.substr(J.size()-siz) == s[i]) {
          J = J.substr(0, J.size()-siz);
          reverse(all(J));
          num = lower_bound(all(info2), J) - info2.begin() + ichi;
          G[j+ichi].emplace_back(num, c[i]);
        }
      }
      else if(J.size() < siz) {
        reverse(all(J));
        if(J == s[i].substr(siz-J.size())) {
          J = s[i].substr(0, siz-J.size());
          num = lower_bound(all(info1), J) - info1.begin();
          G[j+ichi].emplace_back(num, c[i]);
        }
      }
    }
  }

  dijkstra D(ss, G.size());

  if(D[t] == INT64_MAX/3) cout << -1 << endl;
  else cout << D[t] << endl;
}

Measured memory_bytes: 3856