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

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdio>
#include <iostream>
#include <map>
#include <vector>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define IINF (INT_MAX)

using namespace std;

// Library - cycoro - begin -7:26

enum FACE { TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT };

template <class T> class dice {
public:
  dice() {
    // id[FRONT] = 0; id[RIGHT] = 1; id[TOP] = 2;
    // id[BOTTOM] = 3; id[LEFT] = 4; id[BACK] = 5;
    id[TOP] = 0;
    id[FRONT] = 1;
    id[LEFT] = 2;
    id[RIGHT] = 3;
    id[BACK] = 4;
    id[BOTTOM] = 5;
  }
  T &operator[](FACE f) { return var[id[f]]; }
  const T &operator[](FACE f) const { return var[id[f]]; }
  bool operator==(const dice<T> &b) const {
    const dice<T> &a = *this;
    return a[TOP] == b[TOP] && a[BOTTOM] == b[BOTTOM] && a[FRONT] == b[FRONT] &&
           a[BACK] == b[BACK] && a[LEFT] == b[LEFT] && a[RIGHT] == b[RIGHT];
  }

  void roll_x() { roll(TOP, BACK, BOTTOM, FRONT); }
  void roll_y() { roll(TOP, LEFT, BOTTOM, RIGHT); }
  void roll_z() { roll(FRONT, RIGHT, BACK, LEFT); }

  vector<dice> all_rolls() {
    vector<dice> ret;
    for (int k = 0; k < 6; (k & 1 ? roll_y() : roll_x()), ++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        ret.push_back(*this);
    return ret;
  }

  bool equivalent_to(const dice &di) {
    for (int k = 0; k < 6; (k & 1 ? roll_y() : roll_x()), ++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        if (*this == di)
          return true;
    return false;
  }

private:
  void roll(FACE a, FACE b, FACE c, FACE d) {
    T tmp = id[a];
    id[a] = id[b];
    id[b] = id[c];
    id[c] = id[d];
    id[d] = tmp;
  }
  T var[6];
  int id[6];
};

FACE face[] = {FRONT, RIGHT, TOP, BOTTOM, LEFT, BACK};

// Library - cycoro - end 07:34

int n, mincost;
vector<dice<int>> ALL[4];

void dfs(int cur, vector<dice<int>> &tmp) {
  if (cur >= n) {
    int cost = 0;
    // int counter[6];
    map<int, int> counter;
    rep(fc, 6) {
      counter.clear();
      // rep(i,6)counter[i] = 0;
      int mex = 0;
      rep(i, n) {
        counter[tmp[i][face[fc]]]++;
        mex = max(mex, counter[tmp[i][face[fc]]]);
      }
      cost += (n - mex);
      assert(n - mex >= 0);
    }
    mincost = min(cost, mincost);
    return;
  }

  rep(i, ALL[cur].size()) {
    tmp[cur] = ALL[cur][i];
    dfs(cur + 1, tmp);
  }
}

int main() {

  while (cin >> n, n) {
    int idx = 0;
    mincost = IINF;
    map<string, int> getIndex;
    vector<dice<int>> dices(n);
    rep(i, n) {
      rep(j, 6) {
        string color;
        cin >> color;
        if (getIndex.find(color) == getIndex.end())
          getIndex[color] = idx++;
        int index = getIndex[color];
        dices[i][face[j]] = index;
      }
    }

    rep(i, n) ALL[i] = dices[i].all_rolls();
    vector<dice<int>> tmp(n);

    dfs(0, tmp);

    cout << mincost << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdio>
#include <iostream>
#include <map>
#include <unordered_map>
#include <vector>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define IINF (INT_MAX)

using namespace std;

// Library - cycoro - begin -7:26

enum FACE { TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT };

template <class T> class dice {
public:
  dice() {
    // id[FRONT] = 0; id[RIGHT] = 1; id[TOP] = 2;
    // id[BOTTOM] = 3; id[LEFT] = 4; id[BACK] = 5;
    id[TOP] = 0;
    id[FRONT] = 1;
    id[LEFT] = 2;
    id[RIGHT] = 3;
    id[BACK] = 4;
    id[BOTTOM] = 5;
  }
  T &operator[](FACE f) { return var[id[f]]; }
  const T &operator[](FACE f) const { return var[id[f]]; }
  bool operator==(const dice<T> &b) const {
    const dice<T> &a = *this;
    return a[TOP] == b[TOP] && a[BOTTOM] == b[BOTTOM] && a[FRONT] == b[FRONT] &&
           a[BACK] == b[BACK] && a[LEFT] == b[LEFT] && a[RIGHT] == b[RIGHT];
  }

  void roll_x() { roll(TOP, BACK, BOTTOM, FRONT); }
  void roll_y() { roll(TOP, LEFT, BOTTOM, RIGHT); }
  void roll_z() { roll(FRONT, RIGHT, BACK, LEFT); }

  vector<dice> all_rolls() {
    vector<dice> ret;
    for (int k = 0; k < 6; (k & 1 ? roll_y() : roll_x()), ++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        ret.push_back(*this);
    return ret;
  }

  bool equivalent_to(const dice &di) {
    for (int k = 0; k < 6; (k & 1 ? roll_y() : roll_x()), ++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        if (*this == di)
          return true;
    return false;
  }

private:
  void roll(FACE a, FACE b, FACE c, FACE d) {
    T tmp = id[a];
    id[a] = id[b];
    id[b] = id[c];
    id[c] = id[d];
    id[d] = tmp;
  }
  T var[6];
  int id[6];
};

FACE face[] = {FRONT, RIGHT, TOP, BOTTOM, LEFT, BACK};

// Library - cycoro - end 07:34

int n, mincost;
vector<dice<int>> ALL[4];

void dfs(int cur, vector<dice<int>> &tmp) {
  if (cur >= n) {
    int cost = 0;
    unordered_map<int, int> counter;
    rep(fc, 6) {
      counter.clear();
      int mex = 0;
      rep(i, n) {
        counter[tmp[i][face[fc]]]++;
        mex = max(mex, counter[tmp[i][face[fc]]]);
      }
      cost += (n - mex);
      assert(n - mex >= 0);
    }
    mincost = min(cost, mincost);
    return;
  }

  rep(i, ALL[cur].size()) {
    tmp[cur] = ALL[cur][i];
    dfs(cur + 1, tmp);
  }
}

int main() {

  while (cin >> n, n) {
    int idx = 0;
    mincost = IINF;
    map<string, int> getIndex;
    vector<dice<int>> dices(n);
    rep(i, n) {
      rep(j, 6) {
        string color;
        cin >> color;
        if (getIndex.find(color) == getIndex.end())
          getIndex[color] = idx++;
        int index = getIndex[color];
        dices[i][face[j]] = index;
      }
    }

    rep(i, n) ALL[i] = dices[i].all_rolls();
    vector<dice<int>> tmp(n);

    dfs(0, tmp);

    cout << mincost << endl;
  }
  return 0;
}