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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;

enum Face { C1, C2, C3, C4, C5, C6, FACE_SIZE };

struct Dice {
  char face[FACE_SIZE];

  Dice() {}
  Dice(string init) {
    for (int i = 0; i < FACE_SIZE; i++)
      face[i] = init[i];
  }

  void roll_y() { roll(C2, C3, C5, C4); }

  void roll_x() { roll(C2, C6, C5, C1); }

  void roll_z() { roll(C1, C3, C6, C4); }

  void roll(Face a, Face b, Face c, Face d) {
    char tmp = face[d];
    face[d] = face[c];
    face[c] = face[b];
    face[b] = face[a];
    face[a] = tmp;
  }

  inline char at(int a) const { return face[a]; }
};

int dx[] = {0, 0, 1, -1, 0, 0};
int dy[] = {1, -1, 0, 0, 0, 0};
int dz[] = {0, 0, 0, 0, 1, -1};

Face from[] = {C6, C1, C3, C4, C5, C2};
Face to[] = {C1, C6, C4, C3, C2, C5};

Dice dices[8];
Dice rolls[8][64];
int id[2][2][2];

bool allow[2][2][2][64];

bool used[2][2][2];
int cube[2][2][2];

inline bool valid(char a, char b) {
  if (tolower(a) != tolower(b))
    return false;
  if (a == b)
    return false;
  return true;
}

bool dfs(int n) {
  if (n >= 8)
    return true;

  int m = n;
  int x = m % 2;
  m /= 2;
  int y = m % 2;
  m /= 2;
  int z = m;

  for (int i = 0; i < 64; i++)
    if (allow[z][y][x][i]) {
      Dice dice = rolls[id[z][y][x]][i];
      bool ok = true;

      for (int k = 0; k < 6; k++) {
        int nz = z + dz[k];
        int ny = y + dy[k];
        int nx = x + dx[k];

        if (nz < 0 || nz >= 2 || ny < 0 || ny >= 2 || nx < 0 || nx >= 2)
          continue;
        if (!used[nz][ny][nx])
          continue;

        Dice to_dice = rolls[id[nz][ny][nx]][cube[nz][ny][nx]];
        if (!valid(dice.at(from[k]), to_dice.at(to[k]))) {
          ok = false;
          break;
        }
      }

      if (!ok)
        continue;

      used[z][y][x] = true;
      cube[z][y][x] = i;

      if (dfs(n + 1))
        return true;

      used[z][y][x] = false;
    }

  return false;
}

inline bool valid() {
  memset(allow, false, sizeof(allow));
  for (int z = 0; z < 2; z++)
    for (int y = 0; y < 2; y++)
      for (int x = 0; x < 2; x++) {
        int num = 0;
        int cnt = 0;

        for (int kz = 0; kz < 4; kz++)
          for (int ky = 0; ky < 4; ky++)
            for (int kx = 0; kx < 4; kx++) {
              Dice dice = rolls[id[z][y][x]][num];
              bool ok = true;

              for (int k = 0; k < 6; k++) {
                int nz = z + dz[k];
                int ny = y + dy[k];
                int nx = x + dx[k];
                if (nz < 0 || nz >= 2 || ny < 0 || ny >= 2 || nx < 0 || nx >= 2)
                  continue;

                Dice to_dice = dices[id[nz][ny][nx]];

                char from_face = dice.at(from[k]);
                bool check = false;

                for (int face = 0; face < FACE_SIZE; face++) {
                  if (valid(from_face, to_dice.at(face))) {
                    check = true;
                    break;
                  }
                }

                if (!check) {
                  ok = false;
                  break;
                }
              }

              if (ok) {
                allow[z][y][x][num] = true;
                ++cnt;
              }

              ++num;
            }
        if (cnt == 0)
          return false;
      }

  memset(used, false, sizeof(used));
  return dfs(0);
}

inline string solve(const vector<Dice> &dice_vec) {
  for (int i = 0; i < dice_vec.size(); i++) {
    Dice dice = dice_vec[i];

    dices[i] = dice;

    int num = 0;
    for (int kz = 0; kz < 4; kz++, dice.roll_z())
      for (int ky = 0; ky < 4; ky++, dice.roll_y())
        for (int kx = 0; kx < 4; kx++, dice.roll_x()) {
          rolls[i][num] = dice;
          ++num;
        }
  }

  vector<int> perm(dice_vec.size());
  for (int i = 0; i < perm.size(); i++)
    perm[i] = i;

  do {
    for (int z = 0; z < 2; z++)
      for (int y = 0; y < 2; y++)
        for (int x = 0; x < 2; x++) {
          int num = (z * 2 + y) * 2 + x;
          id[z][y][x] = perm[num];
        }
    if (valid())
      return "YES";
  } while (next_permutation(perm.begin(), perm.end()));

  return "NO";
}

int main() {
  string init;
  while (cin >> init) {
    if (init == "0")
      break;

    vector<Dice> dices;
    dices.push_back(Dice(init));

    for (int t = 0; t < 7; t++) {
      cin >> init;
      dices.push_back(Dice(init));
    }

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

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;

enum Face { C1, C2, C3, C4, C5, C6, FACE_SIZE };

struct Dice {
  char face[FACE_SIZE];

  Dice() {}
  Dice(string init) {
    for (int i = 0; i < FACE_SIZE; i++)
      face[i] = init[i];
  }

  void roll_y() { roll(C2, C3, C5, C4); }

  void roll_x() { roll(C2, C6, C5, C1); }

  void roll_z() { roll(C1, C3, C6, C4); }

  void roll(Face a, Face b, Face c, Face d) {
    char tmp = face[d];
    face[d] = face[c];
    face[c] = face[b];
    face[b] = face[a];
    face[a] = tmp;
  }

  char at(Face a) const { return face[a]; }
};

bool valid(char a, char b) {
  if (tolower(a) != tolower(b))
    return false;
  if (a == b)
    return false;
  return true;
}

int dx[] = {0, 0, 1, -1, 0, 0};
int dy[] = {1, -1, 0, 0, 0, 0};
int dz[] = {0, 0, 0, 0, 1, -1};

Face from[] = {C6, C1, C3, C4, C5, C2};
Face to[] = {C1, C6, C4, C3, C2, C5};

// z y x
bool used[2][2][2];
Dice cube[2][2][2];

bool valid(int z, int y, int x, int s, int t, const Dice &d) {
  for (int k = s; k < t; k++) {
    int nz = z + dz[k];
    int ny = y + dy[k];
    int nx = x + dx[k];

    if (nz < 0 || nz >= 2 || ny < 0 || ny >= 2 || nx < 0 || nx >= 2)
      continue;
    if (!used[nz][ny][nx])
      continue;

    if (!valid(d.at(from[k]), cube[nz][ny][nx].at(to[k]))) {
      return false;
    }
  }
  return true;
}

bool dfs(int n, int mask, const vector<Dice> &dices) {
  if (n >= 8)
    return true;

  int id = n;
  int x = id % 2;
  id /= 2;
  int y = id % 2;
  id /= 2;
  int z = id;

  for (int i = 0; i < dices.size(); i++) {
    if ((mask >> i) & 1)
      continue;
    Dice d = dices[i];

    for (int kz = 0; kz < 4; kz++, d.roll_z())
      if (valid(z, y, x, 4, 6, d)) {
        for (int ky = 0; ky < 4; ky++, d.roll_y())
          if (valid(z, y, x, 2, 4, d)) {
            for (int kx = 0; kx < 4; kx++, d.roll_x())
              if (valid(z, y, x, 0, 2, d)) {
                used[z][y][x] = true;
                cube[z][y][x] = d;

                if (dfs(n + 1, mask | (1 << i), dices))
                  return true;

                used[z][y][x] = false;
              }
          }
      }
  }

  return false;
}
string solve(const vector<Dice> &dices) {
  memset(used, false, sizeof(used));
  return dfs(0, 0, dices) ? "YES" : "NO";
}

int main() {
  string init;
  while (cin >> init) {
    if (init == "0")
      break;

    vector<Dice> dices;
    dices.push_back(Dice(init));

    for (int t = 0; t < 7; t++) {
      cin >> init;
      dices.push_back(Dice(init));
    }

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

  return 0;
}