Problem p00899 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <vector>
using namespace std;

typedef pair<int, int> P;

int n;
int d[20][20];
int dp[1 << 15][20];
bool use[20];
vector<string> s;

int rec(int st, int prv) {
  if (st == (1 << n) - 1)
    return 0;
  if (prv >= 0 && dp[st][prv] >= 0)
    return dp[st][prv];

  int res = 10000;

  for (int i = 0; i < n; i++) {
    if ((st >> i) & 1)
      continue;
    int cost = s[i].size();
    if (prv >= 0)
      cost -= d[prv][i];
    res = min(res, rec(st | (1 << i), i) + cost);
  }
  return dp[st][prv] = res;
}

int main() {
  while (cin >> n, n) {
    s.resize(n);
    for (int i = 0; i < n; i++) {
      cin >> s[i];
      use[i] = false;
    }

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (i == j)
          continue;
        if (s[i].size() > s[j].size())
          continue;
        int l = s[i].size();
        for (int k = 0; k + l <= s[j].size(); k++) {
          if (s[i] == s[j].substr(k, l)) {
            use[i] = true;
            break;
          }
        }
      }
    }

    int p = 0;
    for (int i = 0; i < n; i++) {
      if (use[i])
        s.erase(s.begin() + p);
      else
        p++;
    }

    n = s.size();

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (i == j)
          continue;
        d[i][j] = 0;
        int l = min(s[i].size(), s[j].size()) - 1;
        for (int k = l; k >= 1; k--) {
          if (s[i].substr(s[i].size() - k, k) == s[j].substr(0, k)) {
            d[i][j] = k;
            break;
          }
        }
      }
    }

    for (int i = 0; i < (1 << n); i++) {
      for (int j = 0; j < n; j++)
        dp[i][j] = -1;
    }

    cout << rec(0, -1) << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <vector>
using namespace std;

typedef pair<int, int> P;

int n;
int d[20][20];
bool use[20];
int ans;
vector<string> s;

void rec(int depth, int len, int prv) {
  if (depth == n) {
    ans = len;
    return;
  }

  if (n - depth > 1) {
    int sum = 0;
    for (int i = 0; i < n; i++) {
      if (use[i])
        continue;
      int minv = 100;
      for (int j = 0; j < n; j++) {
        if (use[j])
          continue;
        if (i == j)
          continue;
        minv = min(minv, d[i][j]);
      }
      sum += minv;
    }

    // cout << depth << " " << len + sum << endl;
    if (len + sum >= ans)
      return;
  }

  priority_queue<P, vector<P>, greater<P>> q;

  for (int i = 0; i < n; i++) {
    if (!use[i]) {
      if (prv < 0)
        q.push(P(0, i));
      else
        q.push(P(d[prv][i], i));
    }
  }

  while (q.size()) {
    P p = q.top();
    q.pop();
    int cost = p.first, i = p.second;
    use[i] = true;

    int nxt = len;
    if (prv < 0)
      nxt += s[i].size();
    else
      nxt += cost;
    if (ans > nxt)
      rec(depth + 1, nxt, i);

    use[i] = false;
  }
}

int main() {
  while (cin >> n, n) {
    s.resize(n);
    for (int i = 0; i < n; i++) {
      cin >> s[i];
      use[i] = false;
    }

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (i == j)
          continue;
        if (s[i].size() >= s[j].size())
          continue;
        int l = s[i].size();
        for (int k = 0; k + l < s[j].size(); k++) {
          if (s[i] == s[j].substr(k, l)) {
            use[i] = true;
            break;
          }
        }
      }
    }

    int p = 0;
    for (int i = 0; i < n; i++) {
      if (use[i])
        s.erase(s.begin() + p);
      else
        p++;
    }
    n = s.size();

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (i == j)
          continue;
        d[i][j] = s[j].size();
        int l = min(s[i].size(), s[j].size()) - 1;
        for (int k = l; k >= 1; k--) {
          if (s[i].substr(s[i].size() - k, k) == s[j].substr(0, k)) {
            d[i][j] = s[j].size() - k;
            break;
          }
        }
      }
    }

    ans = 0;
    for (int i = 0; i < n; i++) {
      use[i] = false;
      ans += s[i].size();
    }

    /*
    cout << n << endl;
    cout << ans << endl;
    for(int i=0;i<n;i++){
      for(int j=0;j<n;j++){
        cout << d[i][j] << " ";
      }
      cout << endl;
    }
    */
    rec(0, 0, -1);
    cout << ans << endl;
  }
}