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<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define tp tuple<int,int,int>
#define mtp make_tuple
using namespace std;
const int N=10005;
int n,d[N][2],c[N];
map<string,int>id;
string s[N],a[N];
vector<tp>adj[N][2];
priority_queue<tp,vector<tp>,greater<tp>>pq;


main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    memset(d,-1,sizeof d);
    cin>>n;
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        cin>>s[i]>>c[i];
        string t;
        for(int j=0;j<s[i].size();j++)
        {
            t+=s[i][j];
            if(!id[t])
            {
                id[t]=++cnt;
                a[cnt]=t;
            }
        }
        t.clear();
        for(int j=s[i].size()-1;j>=0;j--)
        {
            t+=s[i][j];
            reverse(t.begin(),t.end());
            if(!id[t])
            {
                id[t]=++cnt;
                a[cnt]=t;
            }
            reverse(t.begin(),t.end());
        }
    }
    for(int i=1;i<=cnt;i++)
    {
        string t=a[i];
        reverse(t.begin(),t.end());
        for(int j=1;j<=n;j++)
        {
            if(s[j].size()>=t.size())
            {
                bool kt=true;
                for(int k=0;k<t.size();k++) if(s[j][k]!=t[k]) kt=false;
                string tmp=s[j];
                tmp.erase(0,t.size());
                if(kt)
                {
                    if(s[j].size()==t.size()) adj[i][0].push_back(mtp(0,0,c[j]));
                    else adj[i][0].push_back(mtp(id[tmp],1,c[j]));
                }
            }
        }
        for(int j=1;j<=n;j++)
        {
            if(s[j].size()>=t.size())
            {
                bool kt=true;
                int l=1;
                int r=s[j].size()-t.size();
                for(int k=s[j].size()-1;k>=r;k--)
                {
                    if(s[j][k]!=t[t.size()-l]) kt=false;
                    l++;
                }
                string tmp=s[j];
                tmp.erase(s[j].size()-t.size(),t.size());
                if(kt)
                {
                    if(s[j].size()==t.size()) adj[i][1].push_back(mtp(0,0,c[j]));
                    else adj[i][1].push_back(mtp(id[tmp],0,c[j]));
                }
            }
        }
    }
    d[0][0]=1e18;
    for(int i=1;i<=n;i++)
    {
        d[id[s[i]]][0]=c[i];
        d[id[s[i]]][1]=c[i];
        pq.push(mtp(c[i],id[s[i]],0));
        pq.push(mtp(c[i],id[s[i]],1));
        for(int j=0;j<s[i].size();j++)
        {
            bool kt=true;
            for(int k=j-1,t=j+1;k>=0&&t<s[i].size();k--,t++) if(s[i][k]!=s[i][t]) kt=false;
            if(!kt) continue;
            if(s[i].size()%2&&j==s[i].size()/2) d[0][0]=min(d[0][0],c[i]);
            else if(j<s[i].size()/2)
            {
                string t=s[i];
                t.erase(0,j*2+1);
                d[id[t]][1]=c[i];
                pq.push(mtp(c[i],id[t],1));
                //cout<<t<<' '<<id[t]<<' '<<1<<endl;
            }
            else if(j>=s[i].size()/2)
            {
                int z=s[i].size()-j-1;
                string t;
                for(int k=0;k<s[i].size()-(z*2+1);k++) t+=s[i][k];
                d[id[t]][0]=c[i];
                pq.push(mtp(c[i],id[t],0));
                //cout<<t<<' '<<id[t]<<' '<<0<<endl;
            }
        }
    }
    while(!pq.empty())
    {
        int dist,i,j;
        tie(dist,i,j)=pq.top();
        pq.pop();
        if(d[i][j]!=dist) continue;
        for(auto&x:adj[i][j])
        {
            int c,ni,nj;
            tie(ni,nj,c)=x;
            if(d[ni][nj]>d[i][j]+c||d[ni][nj]==-1)
            {
                d[ni][nj]=d[i][j]+c;
                pq.push(mtp(d[ni][nj],ni,nj));
                //if(ni==13&&nj==1) cout<<i<<' '<<j<<' '<<a[i]<<'\n';
            }
        }
    }
    cout<<d[0][0];
}