#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <fstream>
#include <cassert>
#include <cstring>
#include <unordered_set>
#include <unordered_map>
#include <numeric>
#include <ctime>
#include <bitset>
#include <complex>
#include <chrono>
#include <random>
#include <functional>

using namespace std;

#define int long long

const int N = 53;
const int L = 23;
const int INF = 2e18 + 239;

int dp[2][N][L];

struct State {
	int type;
	int i;
	int len;

	State() {}

	State(int type_, int i_, int len_) {
		type = type_;
		i = i_;
		len = len_;
	}

	bool operator<(const State &other) const {
		return make_tuple(type, i, len) < make_tuple(other.type, other.i, other.len); 
	}
};

int lcp(string a, string b) {
	int ans = 0;
	for (int i = 0; i < (int)a.size() && i < (int)b.size(); i++) {
		if (a[i] == b[i]) {
			ans++;
		} else {
			break;
		}
	}
	return ans;
}

int solve(string p, string s) {
	reverse(s.begin(), s.end());
	return lcp(p, s);
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int n;
	cin >> n;
	vector<string> a(n);
	vector<int> c(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i] >> c[i];
	}
	set<pair<int, State>> S;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j <= (int)a[i].size(); j++) {
			dp[0][i][j] = INF;
			dp[1][i][j] = INF;
		}
		dp[0][i][a[i].size()] = c[i];
		dp[1][i][a[i].size()] = c[i];
		S.insert({c[i], State(0, i, a[i].size())});
		S.insert({c[i], State(1, i, a[i].size())});
	}
	int ans = INF;
	while (!S.empty()) {
		int C;
		State st;
		tie(C, st) = *S.begin();
		S.erase(S.begin());
		for (int j = 0; j < n; j++) {
			if (st.type == 0) {
				string pref = a[st.i].substr(a[st.i].size() - st.len, st.len);
				string suff = a[j];
				int plen = st.len;
				int slen = a[j].size();
				int x = solve(pref, suff);
				plen -= x;
				slen -= x;
				if (!plen && !slen) {
					ans = min(ans, C + c[j]);
				} else {
					if (!slen) {
						if (dp[0][st.i][plen] > C + c[j]) {
							S.erase({dp[0][st.i][plen], State(0, st.i, plen)});
							dp[0][st.i][plen] = C + c[j];
							S.insert({dp[0][st.i][plen], State(0, st.i, plen)});
						}
					}
					if (!plen) {
						if (dp[1][j][slen] > C + c[j]) {
							S.erase({dp[1][j][slen], State(1, j, slen)});
							dp[1][j][slen] = C + c[j];
							S.insert({dp[1][j][slen], State(1, j, slen)});
						}
					}
				}
			} else {
				string suff = a[st.i].substr(0, st.len);
				string pref = a[j];
				int slen = st.len;
				int plen = a[j].size();
				int x = solve(pref, suff);
				plen -= x;
				slen -= x;
				if (!plen && !slen) {
					ans = min(ans, C + c[j]);
				} else {
					if (!slen) {
						if (dp[0][j][plen] > C + c[j]) {
							S.erase({dp[0][j][plen], State(0, j, plen)});
							dp[0][j][plen] = C + c[j];
							S.insert({dp[0][j][plen], State(0, j, plen)});
						} 	
					}
					if (!plen) {
						if (dp[1][st.i][slen] > C + c[j]) {
							S.erase({dp[1][st.i][slen], State(1, st.i, slen)});
							dp[1][st.i][slen] = C + c[j];
							S.insert({dp[1][st.i][slen], State(1, st.i, slen)});
						}
					}
				}
			}
		}
	}
	for (int t = 0; t <= 1; t++) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= (int)a[i].size(); j++) {
				string f;
				if (t) {
					f = a[i].substr(0, j);
				} else {
					f = a[i].substr(a[i].size() - j, j);
				}
				string s = f;
				reverse(f.begin(), f.end());
				if (f == s) {
					ans = min(ans, dp[t][i][j]);	
				}
			}
		}
	}
	if (ans == INF) {
		cout << -1 << '\n';
	} else {
		cout << ans << '\n';
	}
}


Measured memory_bytes: 3220