#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

struct Node {
	int v;
	int len;
	int side;
};

const int maxN = 55;

vector<Node> res[maxN][21][2];
vector<long long> len[maxN][21][2];
long long d[maxN][21][2];

void solve() {
	for (int i = 0; i < maxN; ++i) {
		for (int j = 0; j <= 20; ++j) {
			d[i][j][0] = d[i][j][1] = 1e18;
		}
	}
	int n;
	cin >> n;
	vector<string> s(n);
	vector<long long> cost(n);
	for (int i = 0; i < n; ++i) {
		cin >> s[i] >> cost[i];
	}

	for (int i = 0; i < n; ++i) {
		for (int j = 1; j <= s[i].length(); ++j) {
			if (j == s[i].length()) {
				for (int t = 0; t < n; ++t) {
					for (int k = 1; k <= s[t].length(); ++k) {
						Node nnode1;
						nnode1.v = t;
						nnode1.len = k;
						nnode1.side = 0;
						Node nnode2 = nnode1;
						nnode2.side = 1;
						res[i][j][0].push_back(nnode1); len[i][j][0].push_back(cost[t]);
						res[i][j][0].push_back(nnode2); len[i][j][0].push_back(cost[t]);
						res[i][j][1].push_back(nnode1); len[i][j][1].push_back(cost[t]);
						res[i][j][1].push_back(nnode2); len[i][j][1].push_back(cost[t]);
					}
				}
				continue;
			}
			// on the left, k = 0
			{
				for (int t = 0; t < n; ++t) {
					int lft = (int)s[i].length() - j;
					string nw = s[i].substr(0, lft);
					reverse(nw.begin(), nw.end());
					int good = true;
					for (int v = 0; v < min(nw.length(), s[t].length()); ++v) {
						if (nw[v] != s[t][v]) {
							good = false;
							break;
						}
					}
					if (!good) {
						continue;
					}
					if (nw.length() == s[t].length()) {
						Node nnode{i, s[i].length(), 0};
						Node nnode2{t, s[t].length(), 1};
						res[i][j][0].push_back(nnode); len[i][j][0].push_back(cost[t]);
						res[i][j][0].push_back(nnode2); len[i][j][0].push_back(cost[t]);

						continue;
					}
					Node nnode;
					long long dst = 0;
					if (nw.length() > s[t].length()) {
						nnode.v = i;
						nnode.len = j + s[t].length();
						nnode.side = 0;
						dst = cost[t];
					} else {
						nnode.v = t;
						nnode.len = nw.length();
						nnode.side = 1;
						dst = cost[t];
					}
					res[i][j][0].push_back(nnode);
					len[i][j][0].push_back(dst);
				}
			}

			// on the right, k = 0
			{
				for (int t = 0; t < n; ++t) {
					int lft = (int)s[i].length() - j;
					string nw = s[i].substr(j, lft);
					string cur = s[t];
					reverse(cur.begin(), cur.end());
					int good = true;
					for (int v = 0; v < min(nw.length(), cur.length()); ++v) {
						if (nw[v] != cur[v]) {
							good = false;
							break;
						}
					}
					if (!good) {
						continue;
					}
					if (nw.length() == s[t].length()) {
						Node nnode{ i, s[i].length(), 1 };
						Node nnode2{ t, s[t].length(), 0 };
						res[i][j][1].push_back(nnode); len[i][j][1].push_back(cost[t]);
						res[i][j][1].push_back(nnode2); len[i][j][1].push_back(cost[t]);
						continue;
					}
					Node nnode;
					long long dst = 0;
					if (nw.length() > s[t].length()) {
						nnode.v = i;
						nnode.len = j + s[t].length();
						nnode.side = 1;
						dst = cost[t];
					} else {
						nnode.v = t;
						nnode.len = nw.length();
						nnode.side = 0;
						dst = cost[t];
					}
					res[i][j][1].push_back(nnode);
					len[i][j][1].push_back(dst);
				}
			}
		}
	}

	for (int i = 0; i < n; ++i) {
		string s1 = s[i];
		string s2 = s[i];
		reverse(s1.begin(), s1.end());
		if (s1 == s2) {
			Node nnode;
			nnode.v = i;
			nnode.len = s1.length();
			nnode.side = 0;
			res[n][0][0].push_back(nnode);
			len[n][0][0].push_back(cost[i]);
		}

		for (int j = 0; j < n; ++j) {
			string s1 = s[i];
			string s2 = s[j];

			int len1 = s1.length();
			int len2 = s2.length();

			for (int i1 = 1; i1 <= len1; ++i1) {
				string nw = s1.substr(len1 - i1);
				nw += s2;
				string nw2 = nw;
				reverse(nw2.begin(), nw2.end());
				if (nw == nw2) {
					Node nnode;
					nnode.v = i;
					nnode.len = i1;
					nnode.side = 0;
					res[n][0][0].push_back(nnode);
					len[n][0][0].push_back(cost[i] + cost[j]);
				}
			}

			for (int i1 = 1; i1 <= len1; ++i1) {
				string nw = s2 + s1.substr(0, i1);
				string nw2 = nw;
				reverse(nw2.begin(), nw2.end());
				if (nw == nw2) {
					Node nnode;
					nnode.v = i;
					nnode.len = i1;
					nnode.side = 1;
					res[n][0][0].push_back(nnode);
					len[n][0][0].push_back(cost[i] + cost[j]);
				}
				
			}
		}
	}

	set<pair<long long, vector<int> > > q;
	vector<int> nw = {n, 0, 0};
	q.insert(make_pair(0, nw));

	long long ans = 1e18;

	while (!q.empty()) {
		auto v = q.begin()->second;
		long long curd = q.begin()->first;
		if (v[0] != n) {
			if (v[1] == s[v[0]].length()) {
				ans = min(ans, curd);
			}
		}

		q.erase(q.begin());

		for (int i = 0; i < res[v[0]][v[1]][v[2]].size(); ++i) {
			Node to = res[v[0]][v[1]][v[2]][i];
			long long length = len[v[0]][v[1]][v[2]][i];

			if (d[to.v][to.len][to.side] > curd + length) {
				vector<int> nw = {to.v, to.len, to.side};
				q.erase(make_pair(d[to.v][to.len][to.side], nw));
				d[to.v][to.len][to.side] = curd + length;
				q.insert(make_pair(d[to.v][to.len][to.side], nw));
			}
		}
	}

	cout << ((ans == 1e18) ? -1 : ans) << endl;
}

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios_base::sync_with_stdio(false);

	int t;
	//cin >> t;
	t = 1;

	for (int tt = 0; tt < t; ++tt) {
		solve();
	}


	return 0;
}

Measured memory_bytes: 7980