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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <unordered_set>
#include <utility>

using namespace std;

#define dump(n) cerr << "# " << #n << "=" << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define iter(c) __typeof__((c).begin())
#define foreach(i, c) for (iter(c) i = (c).begin(); i != (c).end(); ++i)
#define all(c) (c).begin(), (c).end()
#define mp make_pair

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef pair<int, int> pii;

struct Dice {
  char face[6];
  void Turn(int a, int b, int c, int d) {
    int x = face[a];
    face[a] = face[b];
    face[b] = face[c];
    face[c] = face[d];
    face[d] = x;
  }
  void TurnX() { Turn(1, 5, 4, 2); }
  void TurnY() { Turn(0, 2, 3, 5); }
  void TurnZ() { Turn(0, 4, 3, 1); }
};
ostream &operator<<(ostream &os, const Dice &d) {
  const char *f = d.face;
  printf("(%c,%c,%c,%c,%c,%c)", f[0], f[1], f[2], f[3], f[4], f[5]);
  return os;
}

// upper case <-> lower case
char flip(char c) { return c ^ 1 << 5; }
bool match(char a, char b) { return flip(a) == b; }

void update(Dice &d, int i) {
  if (i % 2 == 0)
    d.TurnX();
  if (i % 2 == 1)
    d.TurnY();
  if (i % 6 == 5)
    d.TurnZ();
}

string rotatemin(const string &s) {
  string t = s;
  rep(i, s.size()) t = min(t, s.substr(i) + s.substr(0, i));
  return t;
}

string solve(Dice ds[]) {
  vector<unordered_set<string>> upper(256), lower(256);
  int ps[8];
  iota(ps, ps + 8, 0);
  do {
    int bit = 0;
    rep(i, 4) bit |= 1 << ps[i];
    char *fs[4];
    rep(i, 4) fs[i] = ds[ps[i]].face;
    for (int i = 0; i < 24; update(ds[ps[0]], i), i++) {
      for (int j = 0; j < 24; update(ds[ps[1]], j), j++) {
        if (!match(fs[0][0], fs[1][3]))
          continue;
        for (int k = 0; k < 24; update(ds[ps[2]], k), k++) {
          if (!match(fs[1][1], fs[2][4]))
            continue;
          for (int l = 0; l < 24; update(ds[ps[3]], l), l++) {
            if (!match(fs[2][3], fs[3][0]) || !match(fs[3][4], fs[0][1]))
              continue;
            upper[bit].insert(
                rotatemin({fs[0][2], fs[1][2], fs[2][2], fs[3][2]}));
            lower[bit].insert(
                rotatemin({fs[0][5], fs[1][5], fs[2][5], fs[3][5]}));
          }
        }
      }
    }
  } while (reverse(ps + 4, ps + 8), next_permutation(ps, ps + 8));

  rep(i, 256) for (string s : upper[i]) {
    for (char &c : s)
      c = flip(c);
    if (lower[255 ^ i].count(rotatemin(s)))
      return "YES";
  }
  return "NO";
}

int main() {
  for (Dice ds[8];;) {
    rep(i, 8) {
      char *f = ds[i].face;
      cin >> f[2] >> f[0] >> f[1] >> f[4] >> f[3] >> f[5];
    }
    if (ds[0].face[2] == '0')
      break;

    cout << solve(ds) << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <utility>

using namespace std;

#define dump(n) cerr << "# " << #n << "=" << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define iter(c) __typeof__((c).begin())
#define foreach(i, c) for (iter(c) i = (c).begin(); i != (c).end(); ++i)
#define all(c) (c).begin(), (c).end()
#define mp make_pair

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef vector<vs> vvs;

struct Dice {
  char face[6];
  void Turn(int a, int b, int c, int d) {
    int x = face[a];
    face[a] = face[b];
    face[b] = face[c];
    face[c] = face[d];
    face[d] = x;
  }
  void TurnX() { Turn(1, 5, 4, 2); }
  void TurnY() { Turn(0, 2, 3, 5); }
  void TurnZ() { Turn(0, 4, 3, 1); }
};
ostream &operator<<(ostream &os, const Dice &d) {
  const char *f = d.face;
  printf("(%c,%c,%c,%c,%c,%c)", f[0], f[1], f[2], f[3], f[4], f[5]);
  return os;
}

// upper case <-> lower case
char flip(char c) { return c ^ 1 << 5; }
bool match(char a, char b) { return flip(a) == b; }

void update(Dice &d, int i) {
  if (i % 2 == 0)
    d.TurnX();
  if (i % 2 == 1)
    d.TurnY();
  if (i % 6 == 5)
    d.TurnZ();
}

string concat(char a, char b, char c, char d) {
  string s;
  s = s + a + b + c + d;
  string t = s;
  rep(i, 3) {
    rotate(s.begin(), 1 + all(s));
    t = min(t, s);
  }
  return t;
}

string rotatemin(string s) {
  string t = s;
  rep(i, s.size()) t = min(t, s.substr(i) + s.substr(0, i));
  return t;
}

int main() {
  for (Dice ds[8];;) {
    rep(i, 8) {
      char *f = ds[i].face;
      cin >> f[2] >> f[0] >> f[1] >> f[4] >> f[3] >> f[5];
    }
    if (ds[0].face[2] == '0')
      break;

    vector<set<string>> upper(256), lower(256);
    int ps[8];
    iota(ps, ps + 8, 0);
    do {
      int bit = 0;
      rep(i, 4) bit |= 1 << ps[i];
      char *fs[4];
      rep(i, 4) fs[i] = ds[ps[i]].face;
      for (int i = 0; i < 24; update(ds[ps[0]], i), i++) {
        for (int j = 0; j < 24; update(ds[ps[1]], j), j++) {
          if (!match(fs[0][0], fs[1][3]))
            continue;
          for (int k = 0; k < 24; update(ds[ps[2]], k), k++) {
            if (!match(fs[1][1], fs[2][4]))
              continue;
            for (int l = 0; l < 24; update(ds[ps[3]], l), l++) {
              if (!match(fs[2][3], fs[3][0]) || !match(fs[3][4], fs[0][1]))
                continue;

              upper[bit].insert(
                  rotatemin({fs[0][2], fs[1][2], fs[2][2], fs[3][2]}));
              lower[bit].insert(
                  rotatemin({fs[0][5], fs[1][5], fs[2][5], fs[3][5]}));
            }
          }
        }
      }
    } while (reverse(ps + 4, ps + 8), next_permutation(ps, ps + 8));

    bool ok = false;
    rep(i, 256) for (string s : upper[i]) {
      for (char &c : s)
        c = flip(c);
      ok |= binary_search(all(lower[255 ^ i]), rotatemin(s));
    }
    cout << (ok ? "YES" : "NO") << endl;
  }

  return 0;
}