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)

#define taskname "test"

#include <bits/stdc++.h>

using namespace std;

#define sz(x) (int)x.size()
#define fi first
#define se second
#define int long long

typedef pair<int, int> pii;

const int maxn = 55;
const int inf = 1e18;

int n;
string s[maxn];
int c[maxn];

map<pair<string, int>, int> mp;

int ans = inf;

struct info
{
    int val;
    string state;
    int from;

    info(int x, string s, int t) : val(x), state(s), from(t) {}

    bool operator <(const info&other) const
    {
        return val > other.val;
    }
};

priority_queue<info> pq;

void read_input()
{
    cin >> n;
    for(int i = 0; i < n; ++i)
        cin >> s[i] >> c[i];
}

bool ispalind(string s)
{
    for(int i = 0; i < sz(s) / 2; ++i)
        if(s[i] != s[sz(s) - i - 1]) return false;
    return true;
}

void solve()
{
    for(int i = 0; i < n; ++i)
    {
        if(ispalind(s[i]))
            ans = min(ans, (int)c[i]);
        else
        {
            mp[make_pair(s[i], 0)] = c[i];
            pq.push(info((int)c[i], s[i], 0));
            mp[make_pair(s[i], 1)] = c[i];
            pq.push(info((int)c[i], s[i], 1));
        }
    }
    while(!pq.empty())
    {
        info cur = pq.top(); pq.pop();
        string now = cur.state;
        int from = cur.from;
        if(cur.val != mp[make_pair(now, from)])
            continue;
        int val = cur.val;
        if(val >= ans) break;
        for(int i = 0; i < n; ++i)
        {
            bool ok = true;
            for(int j = 0; j < min(sz(now), sz(s[i])); ++j)
            {
                if(from == 0)
                {
                    if(now[j] != s[i][sz(s[i]) - j - 1])
                    {
                        ok = false;
                        break;
                    }
                }
                else
                {
                    if(now[sz(now) - j - 1] != s[i][j])
                    {
                        ok = false;
                        break;
                    }
                }
            }
            if(!ok) continue;
            int nval = val + c[i];
            if(abs(sz(s[i]) - sz(now)) <= 1)
            {
                ans = min(ans, nval);
                continue;
            }
            string t;
            t.resize(max(sz(s[i]), sz(now)) - min(sz(s[i]), sz(now)));
            if(sz(now) > sz(s[i]))
            {
                if(from == 0)
                {
                    for(int j = sz(s[i]); j < sz(now); ++j)
                        t[j - sz(s[i])] = now[j];
                    if(ispalind(t))
                    {
                        ans = min(ans, nval);
                        continue;
                    }
                    if(!mp.count(make_pair(t, 0)) || mp[make_pair(t, 0)] > nval)
                    {
                        mp[make_pair(t, 0)] = nval;
                        pq.push(info(nval, t, 0));
                    }
                }
                else
                {
                    for(int j = 0; j < sz(now) - sz(s[i]); ++j)
                        t[j] = now[j];
                    if(ispalind(t))
                    {
                        ans = min(ans, nval);
                        continue;
                    }
                    if(!mp.count(make_pair(t, 1)) || mp[make_pair(t, 1)] > nval)
                    {
                        mp[make_pair(t, 1)] = nval;
                        pq.push(info(nval, t, 1));
                    }
                }
            }
            else
            {
                if(from == 0)
                {
                    for(int j = 0; j < sz(s[i]) - sz(now); ++j)
                        t[j] = s[i][j];
                    if(ispalind(t))
                    {
                        ans = min(ans, nval);
                        continue;
                    }
                    if(!mp.count(make_pair(t, 1)) || mp[make_pair(t, 1)] > nval)
                    {
                        mp[make_pair(t, 1)] = nval;
                        pq.push(info(nval, t, 1));
                    }
                }
                else
                {
                    for(int j = sz(now); j < sz(s[i]); ++j)
                        t[j - sz(now)] = s[i][j];
                    if(ispalind(t))
                    {
                        ans = min(ans, nval);
                        continue;
                    }
                    if(!mp.count(make_pair(t, 0)) || mp[make_pair(t, 0)] > nval)
                    {
                        mp[make_pair(t, 0)] = nval;
                        pq.push(info(nval, t, 0));
                    }
                }
            }
        }
    }
    assert(ans > 0);
    if(ans == inf) ans = -1;
    cout << ans << '\n';
}

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    read_input();
    solve();
}