Problem:
Score : 600 points

Problem Statement

We have N strings of lowercase English letters: S_1, S_2, \cdots, S_N.

Takahashi wants to make a string that is a palindrome by choosing one or more of these strings - the same string can be chosen more than once - and concatenating them in some order of his choice.

The cost of using the string S_i once is C_i, and the cost of using it multiple times is C_i multiplied by that number of times.

Find the minimum total cost needed to choose strings so that Takahashi can make a palindrome.

If there is no choice of strings in which he can make a palindrome, print -1.

Constraints

1 \leq N \leq 50

1 \leq |S_i| \leq 20

S_i consists of lowercase English letters.

1 \leq C_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
S_1 C_1
S_2 C_2
:
S_N C_N

Output

Print the minimum total cost needed to choose strings so that Takahashi can make a palindrome, or -1 if there is no such choice.

Sample Input 1

3
ba 3
abc 4
cbaa 5

Sample Output 1

7

We have ba, abc, and cbaa.

For example, we can use ba once and abc once for a cost of 7, then concatenate them in the order abc, ba to make a palindrome.
Also, we can use abc once and cbaa once for a cost of 9, then concatenate them in the order cbaa, abc to make a palindrome.

We cannot make a palindrome for a cost less than 7, so we should print 7.

Sample Input 2

2
abcab 5
cba 3

Sample Output 2

11

We can choose abcab once and cba twice, then concatenate them in the order abcab, cba, cba to make a palindrome for a cost of 11.

Sample Input 3

4
ab 5
cba 3
a 12
ab 10

Sample Output 3

8

We can choose a once, which is already a palindrome, but it is cheaper to concatenate ab and cba.

Sample Input 4

2
abc 1
ab 2

Sample Output 4

-1

We cannot make a palindrome, so we should print -1.

Solution in C++ (GCC 9.2.1) (judge verdict: Wrong Answer)

#include <cstdio>
#include <queue>
using namespace std;

typedef long long ll;

constexpr int LMAX = 21;
constexpr ll INF = 1'000'000'000'000'000'007;

bool chmin(ll &a, ll b) {
	if (b < a) {
		a = b;
		return true;
	}
	return false;
}

int length(char *s) {
	int ans = 0;
	for (; s[++ans];)
		;
	return ans;
}

struct tq {
	ll d;
	int n;
	int i;
	bool rev;
	tq(ll ind, int inn, int ini, bool inrev) {
		d = ind;
		n = inn;
		i = ini;
		rev = inrev;
	}
};

struct grtD {
	bool operator()(const tq &a, const tq &b) { return a.d > b.d; }
};

int main() {
	int N;
	scanf("%d", &N);
	char S[N][LMAX];
	int C[N];
	for (int i = 0; i < N; i++) scanf("%s %d", S[i], C + i);
	int L[N];
	for (int i = 0; i < N; i++) L[i] = length(S[i]);

	// dijkstra
	ll dist[N][LMAX][2];
	fill(dist[0][0], dist[N][0], INF);
	priority_queue<tq, vector<tq>, grtD> pq;
	for (int i = 0; i < N; i++) {
		pq.push(tq(C[i], i, 0, false));
		dist[i][0][false] = C[i];
		pq.push(tq(C[i], i, L[i], true));
		dist[i][L[i]][true] = C[i];
	}
	for (; !pq.empty();) {
		tq tmp = pq.top();
		pq.pop();
		if (tmp.d > dist[tmp.n][tmp.i][tmp.rev]) continue;
		if (tmp.rev) {
			if (tmp.i <= 1) {
				printf("%lld\n", tmp.d);
				return 0;
			}
			for (int n = 0; n < N; n++) {
				bool f = true;
				for (int j = 0; f && j < L[n] && j < tmp.i; j++) {
					if (S[n][j] != S[tmp.n][tmp.i - j - 1]) f = false;
				}
				if (!f) continue;
				if (L[n] > tmp.i) {
					int i = tmp.i;
					if (chmin(dist[n][i][false], tmp.d + C[n])) {
						pq.push(tq(dist[n][i][false], n, i, false));
					}
				} else {
					int i = tmp.i - L[n];
					if (chmin(dist[tmp.n][i][true], tmp.d + C[n])) {
						pq.push(tq(dist[tmp.n][i][true], tmp.n, i, true));
					}
				}
			}
		} else {
			if (tmp.i >= L[tmp.n] - 1) {
				printf("%lld\n", tmp.d);
				return 0;
			}
			for (int n = 0; n < N; n++) {
				bool f = true;
				for (int j = 0; f && j + tmp.i < L[tmp.n] && j < L[n]; j++) {
					if (S[n][L[n] - j - 1] != S[tmp.n][tmp.i + j]) f = false;
				}
				if (!f) continue;
				if (L[n] > L[tmp.n] - tmp.i) {
					int i = L[n] + tmp.i - L[tmp.n];
					if (chmin(dist[n][i][true], tmp.d + C[n])) {
						pq.push(tq(dist[n][i][true], n, i, true));
					}
				} else {
					int i = tmp.i + L[n];
					if (chmin(dist[tmp.n][i][false], tmp.d + C[n])) {
						pq.push(tq(dist[tmp.n][i][false], tmp.n, i, false));
					}
				}
			}
		}
	}
	printf("-1\n");
}