//#pragma GCC target("avx2")
//#pragma GCC optimize("O3")
 
#include <x86intrin.h>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <assert.h>
#include <string>
#include <bitset> 
#include <vector>
#include <cmath>                                    
#include <deque>                                    
#include <queue>
#include <iomanip>
#include <stack>
#include <map>
#include <random>
#include <ctime>
#include <unordered_map>
#include <set>
#include <unordered_set>
//#include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
 
//using namespace __gnu_pbds;
using namespace std;

 
//template<typename T> using ordered_set = tree <T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
     
#define F first
#define S second           
#define lb lower_bound               
#define ub upper_bound
#define pb push_back
#define pf push_front    
#define ppb pop_back
#define mp make_pair                                     
#define bpp __builtin_popcountll                                                                                        
#define sqr(x) ((x) * (x)) 
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define in insert
#define ppf pop_front
#define endl '\n'
#define int long long
 
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> pii;
 
const int mod = (int)1e9 + 7;
const int N = (int)3e5 + 123;
const ll inf = (ll)4e18 + 1;
 
const double pi = acos (-1.0);
const double eps = 1e-9;                  
const int dx[] = {0, 0, 1, 0, -1};
const int dy[] = {0, 1, 0, -1, 0};

int n, c[101];
string s[101];
ll dp[101][25][25][2], ans = inf;
set < pair <ll, pair <int, pair < pair <int, int>, int> > > > q;

inline bool is_palindrome (int i, int l, int r) {
   string t = "";
   for (int j = l; j <= r; j ++) t += s[i][j];
   string t1 = t;
   reverse (all (t1));
   return (t1 == t);
}

inline void boost () {
   ios_base :: sync_with_stdio (0);
   cin.tie (0), cout.tie (0);
}
 
inline void Solve () {
   cin >> n;
   for (int i = 1; i <= n; i ++) {
      cin >> s[i] >> c[i];
      for (int j = 0; j < 24; j ++)
         for (int k = 0; k < 24; k ++)
            for (int tp = 0; tp < 2; tp ++)
               dp[i][j][k][tp] = inf;  
   }
   for (int i = 1; i <= n; i ++) {
      dp[i][0][sz (s[i]) - 1][0] = c[i];
      dp[i][0][sz (s[i]) - 1][1] = c[i];
      q.in ({c[i], {i, { {0, sz (s[i]) - 1}, 1} } });
      q.in ({c[i], {i, { {0, sz (s[i]) - 1}, 0} } });
   }  
   while (sz (q)) {
      pair <int, pair < pair <int, int>, int> > wow = q.begin () -> S;
      q.erase (q.begin ());
      int v = wow.F;
      int l = wow.S.F.F;
      int r = wow.S.F.S;
      int tp = wow.S.S;
      if (is_palindrome (v, l, r)) {
         ans = min (ans, dp[v][l][r][tp]);
         continue;
      }
      for (int to = 1; to <= n; to ++) {
         if (tp == 0) {
            int it = sz (s[to]) - 1;
            int L = l;
            while (it >= 0 && L <= r && s[v][L] == s[to][it]) L ++, it --;
            if (it == -1) {
               if (dp[v][L][r][0] > dp[v][l][r][0] + c[to]) {
                  if (q.count ({dp[v][L][r][0], {v, { {L, r}, 0} } })) {
                     q.erase ({dp[v][L][r][0], {v, { {L, r}, 0} } });
                  }
                  dp[v][L][r][0] = dp[v][l][r][0] + c[to];
                  q.in ({dp[v][L][r][0], {v, { {L, r}, 0} } });  
               }
            } 
            else if (L == r + 1) {
               if (dp[to][0][it][1] > dp[v][l][r][0] + c[to]) {
                  if (q.count ({dp[to][0][it][1], {to, { {0, it}, 1} } })) {
                     q.erase ({dp[to][0][it][1], {to, { {0, it}, 1} } });
                  }
                  dp[to][0][it][1] = dp[v][l][r][0] + c[to];
                  q.in ({dp[to][0][it][1], {to, { {0, it}, 1} } });  
               }  
            }
         }
         else {
            int it = 0;
            int R = r;
            while (it < sz (s[to]) && R >= l && s[v][R] == s[to][it]) R --, it ++;
            if (it == sz (s[to])) {
               if (R == -1) {
                  ans = min (ans, dp[v][l][r][1] + c[to]);
                  continue;
               }
               if (dp[v][l][R][1] > dp[v][l][r][1] + c[to]) {
                  if (q.count ({dp[v][l][R][1], {v, { {l, R}, 1} } })) {
                     q.erase ({dp[v][l][R][1], {v, { {l, R}, 1} } });
                  }
                  dp[v][l][R][1] = dp[v][l][r][1] + c[to];
                  q.in ({dp[v][l][R][1], {v, { {l, R}, 1} } });  
               }
            }
            else if (R == l - 1) {
               if (dp[to][it][sz (s[to]) - 1][0] > dp[v][l][r][1] + c[to]) {
                  if (q.count ({dp[to][it][sz (s[to]) - 1][0], {to, { {it, sz (s[to]) - 1}, 0} } })) {
                     q.erase ({dp[to][it][sz (s[to]) - 1][0], {to, { {it, sz (s[to]) - 1}, 0} } });
                  }
                  dp[to][it][sz (s[to]) - 1][0] = dp[v][l][r][1] + c[to];
                  q.in ({dp[to][it][sz (s[to]) - 1][0], {to, { {it, sz (s[to]) - 1}, 0} } });  
               }
            }
         }   
      }
   }
   if (ans == inf) ans = -1;
   cout << ans;              
}               
 
signed main () {                                       
  // #ifdef QWERTY
   //   freopen("input", "r", stdin);
   //#endif
  // freopen (".in", "r", stdin);    
  // freopen (".out", "w", stdout);              
   boost ();
   int tt = 1;
   
   //cin >> tt;   
   while (tt --) {
      Solve ();
   }                                               
   return 0;      
}                   

Measured memory_bytes: 4144