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

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;

#define reep(i, f, t) for (int i = f; i < int(t); ++i)
#define rep(i, n) reep(i, 0, n)

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;

struct Dice {
  char f[8];
  int count;

  Dice() : count(0) {}

  void swap(int a, int b, int c, int d) {
    char tmp = f[a];
    f[a] = f[b];
    f[b] = f[c];
    f[c] = f[d];
    f[d] = tmp;
  }

  void xroll() { swap(0, 1, 5, 4); }

  void yroll() { swap(1, 2, 4, 3); }

  void zroll() { swap(0, 2, 5, 3); }

  void next() {
    zroll();
    if (count % 8 == 3)
      xroll();
    else if (count % 8 == 7)
      yroll();
    ++count;
  }

  bool operator<(const Dice &d) const { return strcmp(f, d.f) < 0; }
};

bool okok(char a, char b) {
  return a != b && (tolower(a) == b || a == tolower(b));
}

bool search(Dice d[8], int depth) {
  if (depth == 8)
    return true;

  rep(i, 24) {
    bool ok;
    if (depth == 1)
      ok = okok(d[0].f[2], d[1].f[3]);
    else if (depth == 2)
      ok = okok(d[0].f[4], d[2].f[1]);
    else if (depth == 3)
      ok = okok(d[1].f[4], d[3].f[1]) && okok(d[2].f[2], d[3].f[3]);
    else if (depth == 4)
      ok = okok(d[0].f[0], d[4].f[5]);
    else if (depth == 5)
      ok = okok(d[1].f[0], d[5].f[5]) && okok(d[4].f[2], d[5].f[3]);
    else if (depth == 6)
      ok = okok(d[2].f[0], d[6].f[5]) && okok(d[4].f[4], d[6].f[1]);
    else
      ok = okok(d[3].f[0], d[7].f[5]) && okok(d[5].f[4], d[7].f[1]) &&
           okok(d[6].f[2], d[7].f[3]);

    if (ok && search(d, depth + 1))
      return true;

    d[depth].next();
  }
  return false;
}

int main() {
  Dice dice[8];
  while (1) {
    bool quit = false;
    rep(i, 8) {
      scanf("%s", dice[i].f);
      if (dice[i].f[0] == '0') {
        quit = true;
        break;
      }
    }
    if (quit)
      break;

    int ans = false;
    sort(dice, dice + 8);
    do {
      bool ok = false;
      set<int> memo;
      rep(i, 24) {
        char c[3] = {dice[0].f[0], dice[0].f[2], dice[0].f[4]};
        sort(c, c + 3);
        int key = (c[0] << 16) + (c[1] << 8) + c[2];
        if (!memo.count(key)) {
          memo.insert(key);
          if (search(dice, 1)) {
            ok = true;
            break;
          }
        }
        dice[0].next();
      }
      if (ok) {
        ans = true;
        break;
      }
    } while (next_permutation(dice + 1, dice + 8));
    puts(ans ? "YES" : "NO");
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;

#define reep(i, f, t) for (int i = f; i < int(t); ++i)
#define rep(i, n) reep(i, 0, n)

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;

struct Dice {
  char f[8];
  int count;

  Dice() : count(0) {}

  void swap(int a, int b, int c, int d) {
    char tmp = f[a];
    f[a] = f[b];
    f[b] = f[c];
    f[c] = f[d];
    f[d] = tmp;
  }

  void xroll() { swap(0, 1, 5, 4); }

  void yroll() { swap(1, 2, 4, 3); }

  void zroll() { swap(0, 2, 5, 3); }

  void next() {
    if (count % 8 == 3)
      xroll();
    else if (count % 8 == 7)
      yroll();
    else
      zroll();
    ++count;
  }

  bool operator<(const Dice &d) const { return strcmp(f, d.f) < 0; }
};

bool okok(char a, char b) {
  return a != b && (tolower(a) == b || a == tolower(b));
}

bool search(Dice d[8], int depth) {
  if (depth == 8)
    return true;

  rep(i, 24) {
    bool ok = true;
    if (depth == 1)
      ok = okok(d[0].f[2], d[1].f[3]);
    else if (depth == 2)
      ok = okok(d[0].f[4], d[2].f[1]);
    else if (depth == 3)
      ok = okok(d[1].f[4], d[3].f[1]) && okok(d[2].f[2], d[3].f[3]);
    else if (depth == 4)
      ok = okok(d[0].f[0], d[4].f[5]);
    else if (depth == 5)
      ok = okok(d[1].f[0], d[5].f[5]) && okok(d[4].f[2], d[5].f[3]);
    else if (depth == 6)
      ok = okok(d[2].f[0], d[6].f[5]) && okok(d[4].f[4], d[6].f[1]);
    else if (depth == 7)
      ok = okok(d[3].f[0], d[7].f[5]) && okok(d[5].f[4], d[7].f[1]) &&
           okok(d[6].f[2], d[7].f[3]);

    if (ok && search(d, depth + 1))
      return true;

    d[depth].next();
  }
  return false;
}

int main() {
  Dice dice[8];
  while (1) {
    bool quit = false;
    rep(i, 8) {
      if (scanf("%s", dice[i].f), dice[i].f[0] == '0') {
        quit = true;
        break;
      }
    }
    if (quit)
      break;

    int ans = false;
    sort(dice, dice + 8);
    do {
      if (search(dice, 0)) {
        ans = true;
        break;
      }
    } while (next_permutation(dice + 1, dice + 8));
    puts(ans ? "YES" : "NO");
  }

  return 0;
}