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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <string>
using namespace std;
const int maxn = 20;
const int inf = 0x3f3f3f3f;
char str[maxn][50];
int G[maxn][maxn];
int dp[1 << 15][15];
bool ok[maxn];
int n;

int cal(int x, int y) {
  int len1 = strlen(str[x]);
  int len2 = strlen(str[y]);
  int i, j, k;
  int ans = 0, tmp;
  for (i = 0; i < len1; ++i) {
    tmp = 0;
    for (j = i, k = 0; j < len1 && k < len2; ++j, ++k) {
      if (str[x][j] == str[y][k]) {
        tmp++;
      } else {
        break;
      }
    }
    if (k == len2) {
      ans = max(ans, tmp);
    } else if (j == len1) {
      ans = max(ans, tmp);
    }
  }
  return len2 - ans;
}

void bulid() {
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (i == j)
        G[i][j] = 0;
      else {
        G[i][j] = cal(i, j);
      }
    }
  }
  memset(ok, false, sizeof(ok));
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (i == j)
        continue;
      if (strstr(str[i], str[j])) {
        ok[j] = true;
      }
    }
  }
}

void solve() {
  memset(dp, inf, sizeof(dp));
  for (int i = 0; i < n; ++i) {
    dp[1 << i][i] = strlen(str[i]);
  }
  for (int i = 0; i < (1 << n); ++i) {
    for (int j = 0; j < n; ++j) {
      if (dp[i][j] == inf || ok[j]) {
        continue;
      }
      for (int k = 0; k < n; ++k) {
        if (ok[k])
          continue;
        if ((i & (1 << k)) == 0) {
          dp[i | (1 << k)][k] = min(dp[i | (1 << k)][k], dp[i][j] + G[j][k]);
        }
      }
    }
  }
}

int main() {

  // freopen("aa.in", "r", stdin);

  while (scanf("%d", &n) && n) {
    for (int i = 0; i < n; ++i) {
      scanf("%s", str[i]);
    }
    bulid();
    solve();
    int ans = inf;
    int x = (1 << n) - 1;
    for (int i = 0; i < n; ++i) {
      if (ok[i]) {
        x &= (~(1 << i));
      }
    }
    for (int i = 0; i < n; ++i) {
      ans = min(ans, dp[x][i]);
    }
    printf("%d\\n", ans);
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
typedef long long ll;
int n, m;
int g[20][20];
char s[20][50];
int l[20];
int path(char *s1, char *s2) {
  int l1 = strlen(s1);
  int l2 = strlen(s2);
  int l = max(l1, l2);
  int lm = min(l1, l2);
  int res = 0;
  for (int i = 1; i <= lm; i++) {
    bool ok = true;
    for (int j = 0; j < i; j++)
      if (s1[l1 - i + j] != s2[j]) {
        ok = false;
        break;
      }
    if (ok)
      res = i;
  }
  return res;
}
int ans = 0;
bool vis[20];
void dfs(int u, int cnt, int len) {
  if (len >= ans)
    return;
  if (cnt == n)
    ans = len;
  for (int j = 0; j < n; j++)
    if (!vis[j]) {
      vis[j] = true;
      dfs(j, cnt + 1, len + l[j] - g[u][j]);
      vis[j] = false;
    }
}

int main() {
  //    freopen("in.txt","r",stdin);
  while (~scanf("%d", &n) && n) {
    memset(g, -1, sizeof g);
    int lsum = 0;
    for (int i = 0; i < n; i++)
      scanf("%s", s[i]), l[i] = strlen(s[i]), lsum += l[i];

    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        g[i][j] = path(s[i], s[j]);
    ans = 99999999;
    for (int i = 0; i < n; i++) {
      memset(vis, false, sizeof vis);
      vis[i] = true;
      dfs(i, 1, l[i]);
    }
    cout << ans << endl;
  }
  return 0;
}