#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <algorithm>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define repi(i,a,b) for(ll i=(a);i<(b);++i)
#define rep(i,a) repi(i,0,a)
#define repdi(i,a,b) for(ll i=(a)-1;i>=(b);--i)
#define repd(i,a) repdi(i,a,0)
#define itr(it,a) for( auto it = (a).begin(); it != (a).end(); ++it )
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define endl '\n'
#define debug(x) std::cerr << #x << " = " << (x) << endl;

using ll = long long;
using P = std::pair<ll, ll>;

constexpr ll INF = 1ll<<60;

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

template<class S, class T>
std::ostream& operator<< ( std::ostream& out, const std::pair<S,T>& a )
{ std::cout << '(' << a.first << ", " << a.second << ')'; return out; }

template<class T>
std::ostream &operator<< ( std::ostream& out, const std::vector<T>& a )
{ std::cout << '['; rep( i, a.size() ){ std::cout << a[i]; if( i != a.size()-1 ) std::cout << ", "; } std::cout << ']'; return out; }

using SVec = std::vector<std::string>;
using VVec = std::vector<std::vector<ll>>;

ll N;
SVec S, rS;
std::vector<ll> C;
VVec ip, rip;
std::vector<std::vector<P>> G;
std::vector<ll> dist;

std::string rev( std::string s ) {
  std::reverse( all(s) );

  return s;
}

void add_edge( const SVec &S, const SVec &rS, const VVec &ip, const VVec &rip ) {
  rep( i, N ) {
    ll l = S[i].size();

    rep( j, l ) {
      rep( ri, N ) {
        ll v = ip[i][j];
        ll nl = rS[ri].size();
        ll w = std::min( l-j, nl );

        if( S[i].substr( j, w ) != rS[ri].substr( 0, w ) )
          continue;

        ll u = 0;

        if( nl > w ) {
          u = rip[ri][w];
        } else if( l-j > w ) {
          u = ip[i][j+w];
        }

        G[v].emplace_back( u, C[ri] );
      }
    }
  }

  return;
}

ll ans;

void accMin( const SVec &S, const VVec &ip ) {
  rep( i, N ) {
    ll l = S[i].size();

    rep( j, l ) {
      std::string t = S[i].substr( j );

      if( t == rev(t) )
        chmin( ans, dist[ip[i][j]] );
    }
  }
}

int main() {
  std::cin >> N;

  ll cnt = 1;

  S.resize( N+10 );
  rS.resize( N+10 );
  ip.resize( N+10 );
  rip.resize( N+10 );
  C.resize( N+10 );

  rep( i, N ) {
    std::cin >> S[i] >> C[i];

    ip[i].resize( S[i].size()+10 );

    rep( j, S[i].size() )
      ip[i][j] = cnt++;
  }

  rep( i, N ) {
    rS[i] = rev(S[i]);

    rip[i].resize( rS[i].size()+10 );

    rep( j, rS[i].size() )
      rip[i][j] = cnt++;
  }

  G.resize( cnt+10 );

  add_edge( S, rS, ip, rip );
  add_edge( rS, S, rip, ip );

  std::priority_queue<P, std::vector<P>, std::greater<P>> pque;

  dist.resize( cnt+10 );

  std::fill( all(dist), INF );
  
  rep( i, N ) {
    pque.emplace( C[i], ip[i][0] );

    dist[ip[i][0]] = C[i];
  }

  while( !pque.empty() ) {
    P p = pque.top(); pque.pop();
    ll d = p.first, v = p.second;

    if( dist[v] < d )
      continue;

    for( auto u : G[v] ) {
      if( chmin( dist[u.first], d+u.second ) ) {
        pque.emplace( dist[u.first], u.first );
      }
    }
  }

  ans = dist[0];

  accMin( S, ip );
  accMin( rS, rip );

  std::cout << (ans==INF ? -1 : ans) << endl;

  return 0;
}

Measured memory_bytes: 3788