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

// 半数列挙で答えが8以下かを判定する.
// 順列は, 16進数で表現する.
#include <algorithm>
#include <iostream>
#include <vector>
#define int long long
using namespace std;

int n;
int a[10], decA, basePermDec;
vector<int> perms[2][5];

void dfs(int type, int depth, int maxDepth, int nowP) {
  perms[type][depth].push_back(nowP);
  if (depth == maxDepth)
    return;
  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      int nextP = nowP & ((1LL << (4 * (j + 1))) - 1);
      nextP = (nextP >> (4 * i)) << (4 * i);
      nextP = nowP - nextP;
      for (int k = 0; k <= j - i; k++) {
        int idl = i + k;
        int idr = j - k;
        nextP += ((nowP >> (4 * idr)) & 15) << (4 * idl);
      }
      dfs(type, depth + 1, maxDepth, nextP);
    }
  }
}

bool isMatch(int depth1, int depth2) {
  vector<int> &a = perms[0][depth1];
  vector<int> &b = perms[1][depth2];
  int i, j;

  if (a.size() == 0 || b.size() == 0)
    return false;

  j = 0;
  for (i = 0; i < a.size(); i++) {
    for (; j < b.size(); j++) {
      if (a[i] <= b[j]) {
        break;
      }
    }
    if (j < b.size() && a[i] == b[j])
      return true;
  }
  return false;
}

signed main() {
  int i, j;

  cin >> n;
  for (i = 0; i < n; i++) {
    cin >> a[i];
    a[i]--;
  }
  for (i = 0; i < n; i++)
    decA += a[i] << (4 * i);
  for (i = 0; i < n; i++)
    basePermDec += i << (4 * i);
  dfs(0, 0, 4, basePermDec);
  dfs(1, 0, 4, decA);

  for (i = 0; i < 2; i++) {
    for (j = 0; j < 5; j++) {
      sort(perms[i][j].begin(), perms[i][j].end());
      perms[i][j].erase(unique(perms[i][j].begin(), perms[i][j].end()),
                        perms[i][j].end());
    }
  }

  int ans = 9;
  for (i = 0; i <= 4; i++) {
    for (j = 0; j <= 4; j++) {
      if (isMatch(i, j)) {
        ans = min(ans, i + j);
      }
    }
  }
  cout << ans << endl;
  return 0;
}


Error: TLE

Fixed submission:

// yarudake => ??¨???????????????O(N! * N^3)??§???????¶???????
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

int n;
int a[10];
int dp[5000000];

//[l, r)
void reverse(vector<int> &vec, int l, int r) {
  while (l < r - 1) {
    swap(vec[l], vec[r - 1]);
    l++;
    r--;
  }
}

//??¶?????¨???????¨???¶????????¨(?????????)
int encode(vector<int> &vec) {
  int val[11]; // val[i] = ???i????????????????°??????????

  int fact = 1;
  for (int i = 0; i < vec.size(); i++) {
    val[i + 1] = i;
    fact *= i + 1;
  }
  fact /= vec.size();

  int ret = 0;
  for (int i = 0; i < vec.size(); i++) {
    ret += fact * val[vec[i]];
    if (i + 1 < vec.size())
      fact /= (vec.size() - 1 - i);
    for (int j = vec[i] + 1; j <= vec.size(); j++) {
      val[j]--;
    }
  }
  return ret;
}

int main() {
  int i;

  cin >> n;
  for (i = 0; i < n; i++)
    cin >> a[i];
  for (i = 0; i < 5000000; i++)
    dp[i] = 114514;

  typedef vector<int> V;

  V first;
  for (i = 0; i < n; i++)
    first.push_back(a[i]);

  queue<V> que;
  que.push(first);
  dp[encode(first)] = 0;
  while (!que.empty()) {
    V now = que.front();
    que.pop();
    int cst = dp[encode(now)];

    for (int l = 0; l < n; l++) {
      for (int r = l + 1; r <= n; r++) {
        reverse(now, l, r);
        if (dp[encode(now)] > cst + 1) {
          dp[encode(now)] = cst + 1;
          que.push(now);
        }
        reverse(now, l, r);
      }
    }
  }

  cout << dp[0] << endl;
  return 0;
}