Problem p02587 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll dp[51][2][21];
ll ndp[51][2][21];
string s[51];
ll c[51];

bool good(int pos, int flag, int len) {
  int sz = s[pos].size();
  if (flag == 0) {
    int l = sz - len, r = sz - 1;
    for (; l <= r; l++, r--) {
      if (s[pos][l] != s[pos][r])
        return false;
    }
    return true;
  } else {
    int l = 0, r = len - 1;
    for (; l <= r; l++, r--) {
      if (s[pos][l] != s[pos][r])
        return false;
    }
    return true;
  }
}

void solve() {
  int n;
  cin >> n;
  memset(dp, -1, sizeof dp);
  for (int i = 1; i <= n; i++) {
    for (int flag = 0; flag <= 1; flag++) {
      for (int len = 1; len <= 20; len++) {
        dp[i][flag][len] = 1e18;
      }
    }
  }
  ll ans = 1e18;
  for (int i = 1; i <= n; i++) {
    cin >> s[i] >> c[i];
    int sz = s[i].size();
    dp[i][0][sz] = c[i]; // prefix
    dp[i][1][sz] = c[i]; // suffix
    if (good(i, 0, sz)) {
      ans = min(ans, c[i]);
    }
  }
  for (int iter = 0; iter < 50 * 20 * 2 + 200; iter++) {
    for (int i = 1; i <= n; i++) {
      int sz1 = s[i].size();
      for (int flag = 0; flag <= 1; flag++) {
        for (int len = 1; len <= sz1; len++) {
          if (dp[i][flag][len] == 1e18)
            continue;
          for (int j = 1; j <= n; j++) {
            int sz2 = s[j].size();
            if (flag == 0) {
              // should take in the suffix, have i-th in the end with last len
              // symbols
              int equals = 1, pos1 = sz1 - len, pos2 = sz2 - 1;
              for (; pos1 < sz1 && pos2 >= 0; pos1++, pos2--) {
                equals &= (s[i][pos1] == s[j][pos2]);
              }
              if (len > sz2 && equals) {
                dp[i][0][len - sz2] =
                    min(dp[i][0][len - sz2], dp[i][0][len] + c[j]);
                if (good(i, 0, len - sz2)) {
                  ans = min(ans, dp[i][0][len - sz2]);
                }
              }
              if (len < sz2 && equals) {
                // cout << "i=" << i << " len=" << len << " j=" << j << "
                // sz2-len=" << sz2 - len << endl;
                dp[j][1][sz2 - len] =
                    min(dp[j][1][sz2 - len], dp[i][0][len] + c[j]);
                if (good(j, 1, sz2 - len)) {
                  ans = min(ans, dp[j][1][sz2 - len]);
                }
              }
              if (len == sz2 && equals) {
                // cout << "1   " << "i=" << i << " len=" << len << " j=" << j
                // << endl;
                ans = min(ans, dp[i][0][len] + c[j]);
              }
            } else {
              // should take in the prefix, have first len symbols
              int equals = 1, pos1 = len - 1, pos2 = 0;
              for (; pos1 >= 0 && pos2 < sz2; pos1--, pos2++) {
                equals &= (s[i][pos1] == s[j][pos2]);
              }
              if (len > sz2 && equals) {
                dp[i][1][len - sz2] =
                    min(dp[i][1][len - sz2], dp[i][1][len] + c[j]);
                if (good(i, 1, len - sz2)) {
                  ans = min(ans, dp[i][1][len - sz2]);
                }
              }
              if (len < sz2 && equals) {
                dp[j][0][sz2 - len] =
                    min(dp[j][0][sz2 - len], dp[i][1][len] + c[j]);
                if (good(j, 0, sz2 - len)) {
                  ans = min(ans, dp[j][0][sz2 - len]);
                  // cout << "2   " << "i=" << i << " len=" << len << " j=" << j
                  // << endl;
                }
              }
              if (len == sz2 && equals) {
                // cout << "2   " << "i=" << i << " len=" << len << " j=" << j
                // << endl;
                ans = min(ans, dp[i][1][len] + c[j]);
              }
            }
          }
        }
      }
    }
  }
  if (ans == 1e18)
    cout << -1;
  else
    cout << ans;
}

int main() {
  ios::sync_with_stdio(NULL), cin.tie(0), cout.tie(0);
  cout.setf(ios::fixed), cout.precision(20);
  solve();
}


Fixed submission:
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll dp[51][2][21];
ll ndp[51][2][21];
string s[51];
ll c[51];

bool good(int pos, int flag, int len) {
  int sz = s[pos].size();
  if (flag == 0) {
    int l = sz - len, r = sz - 1;
    for (; l <= r; l++, r--) {
      if (s[pos][l] != s[pos][r])
        return false;
    }
    return true;
  } else {
    int l = 0, r = len - 1;
    for (; l <= r; l++, r--) {
      if (s[pos][l] != s[pos][r])
        return false;
    }
    return true;
  }
}

void solve() {
  int n;
  cin >> n;
  memset(dp, -1, sizeof dp);
  for (int i = 1; i <= n; i++) {
    for (int flag = 0; flag <= 1; flag++) {
      for (int len = 1; len <= 20; len++) {
        dp[i][flag][len] = 1e18;
      }
    }
  }
  ll ans = 1e18;
  for (int i = 1; i <= n; i++) {
    cin >> s[i] >> c[i];
    int sz = s[i].size();
    dp[i][0][sz] = c[i]; // prefix
    dp[i][1][sz] = c[i]; // suffix
    if (good(i, 0, sz)) {
      ans = min(ans, c[i]);
    }
  }
  for (int iter = 0; iter < 50 * 10; iter++) {
    for (int i = 1; i <= n; i++) {
      int sz1 = s[i].size();
      for (int flag = 0; flag <= 1; flag++) {
        for (int len = 1; len <= sz1; len++) {
          if (dp[i][flag][len] == 1e18)
            continue;
          for (int j = 1; j <= n; j++) {
            int sz2 = s[j].size();
            if (flag == 0) {
              // should take in the suffix, have i-th in the end with last len
              // symbols
              int equals = 1, pos1 = sz1 - len, pos2 = sz2 - 1;
              for (; pos1 < sz1 && pos2 >= 0; pos1++, pos2--) {
                equals &= (s[i][pos1] == s[j][pos2]);
              }
              if (len > sz2 && equals) {
                dp[i][0][len - sz2] =
                    min(dp[i][0][len - sz2], dp[i][0][len] + c[j]);
                if (good(i, 0, len - sz2)) {
                  ans = min(ans, dp[i][0][len - sz2]);
                }
              }
              if (len < sz2 && equals) {
                // cout << "i=" << i << " len=" << len << " j=" << j << "
                // sz2-len=" << sz2 - len << endl;
                dp[j][1][sz2 - len] =
                    min(dp[j][1][sz2 - len], dp[i][0][len] + c[j]);
                if (good(j, 1, sz2 - len)) {
                  ans = min(ans, dp[j][1][sz2 - len]);
                }
              }
              if (len == sz2 && equals) {
                // cout << "1   " << "i=" << i << " len=" << len << " j=" << j
                // << endl;
                ans = min(ans, dp[i][0][len] + c[j]);
              }
            } else {
              // should take in the prefix, have first len symbols
              int equals = 1, pos1 = len - 1, pos2 = 0;
              for (; pos1 >= 0 && pos2 < sz2; pos1--, pos2++) {
                equals &= (s[i][pos1] == s[j][pos2]);
              }
              if (len > sz2 && equals) {
                dp[i][1][len - sz2] =
                    min(dp[i][1][len - sz2], dp[i][1][len] + c[j]);
                if (good(i, 1, len - sz2)) {
                  ans = min(ans, dp[i][1][len - sz2]);
                }
              }
              if (len < sz2 && equals) {
                dp[j][0][sz2 - len] =
                    min(dp[j][0][sz2 - len], dp[i][1][len] + c[j]);
                if (good(j, 0, sz2 - len)) {
                  ans = min(ans, dp[j][0][sz2 - len]);
                  // cout << "2   " << "i=" << i << " len=" << len << " j=" << j
                  // << endl;
                }
              }
              if (len == sz2 && equals) {
                // cout << "2   " << "i=" << i << " len=" << len << " j=" << j
                // << endl;
                ans = min(ans, dp[i][1][len] + c[j]);
              }
            }
          }
        }
      }
    }
  }
  if (ans == 1e18)
    cout << -1;
  else
    cout << ans;
}

int main() {
  ios::sync_with_stdio(NULL), cin.tie(0), cout.tie(0);
  cout.setf(ios::fixed), cout.precision(20);
  solve();
}