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

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

class Dice {
public:
  void setPos(int num) {

    for (int i = 0; i < 6; i++)
      work[i] = words[i];

    switch (num) {
    case 0:
      setWords(work[4], work[0], work[2], work[3], work[5], work[1]);
      break;
    case 1:
      setWords(work[5], work[4], work[2], work[3], work[1], work[0]);
      break;
    case 2:
      setWords(work[1], work[5], work[2], work[3], work[0], work[4]);
      break;
    case 3:
      setWords(work[0], work[1], work[2], work[3], work[4], work[5]);
      break;
    case 4:
      setWords(work[2], work[1], work[5], work[0], work[4], work[3]);
      break;
    case 5:
      setWords(work[4], work[2], work[5], work[0], work[3], work[1]);
      break;
    case 6:
      setWords(work[3], work[4], work[5], work[0], work[1], work[2]);
      break;
    case 7:
      setWords(work[1], work[3], work[5], work[0], work[2], work[4]);
      break;
    case 8:
      setWords(work[5], work[3], work[4], work[1], work[2], work[0]);
      break;
    case 9:
      setWords(work[2], work[5], work[4], work[1], work[0], work[3]);
      break;
    case 10:
      setWords(work[0], work[2], work[4], work[1], work[3], work[5]);
      break;
    case 11:
      setWords(work[3], work[0], work[4], work[1], work[5], work[2]);
      break;
    case 12:
      setWords(work[1], work[0], work[3], work[2], work[5], work[4]);
      break;
    case 13:
      setWords(work[5], work[1], work[3], work[2], work[4], work[0]);
      break;
    case 14:
      setWords(work[4], work[5], work[3], work[2], work[0], work[1]);
      break;
    case 15:
      setWords(work[0], work[4], work[3], work[2], work[1], work[5]);
      break;
    case 16:
      setWords(work[2], work[4], work[0], work[5], work[1], work[3]);
      break;
    case 17:
      setWords(work[1], work[2], work[0], work[5], work[3], work[4]);
      break;
    case 18:
      setWords(work[3], work[1], work[0], work[5], work[4], work[2]);
      break;
    case 19:
      setWords(work[4], work[3], work[0], work[5], work[2], work[1]);
      break;
    case 20:
      setWords(work[0], work[3], work[1], work[4], work[2], work[5]);
      break;
    case 21:
      setWords(work[2], work[0], work[1], work[4], work[5], work[3]);
      break;
    case 22:
      setWords(work[5], work[2], work[1], work[4], work[3], work[0]);
      break;
    case 23:
      setWords(work[3], work[5], work[1], work[4], work[0], work[2]);
      break;
    }
  }

  char getTop() { return words[0]; }

  char getEast() { return words[2]; }

  char getNorth() { return words[1]; }

  char getWest() { return words[3]; }

  char getBottom() { return words[5]; }

  char getSouth() { return words[4]; }

  void setWords(char w0, char w1, char w2, char w3, char w4, char w5) {
    words[0] = w0;
    words[1] = w1;
    words[2] = w2;
    words[3] = w3;
    words[4] = w4;
    words[5] = w5;
  }

  void setFirst(char c1, char c2, char c3, char c4, char c5, char c6) {
    words[0] = c1;
    words[1] = c5;
    words[2] = c3;
    words[3] = c4;
    words[4] = c2;
    words[5] = c6;
  }

  void set(Dice arg) {
    for (int i = 0; i < 6; i++) {
      words[i] = arg.words[i];
    }
  }

  char words[6];
  char work[6];
};

struct Puzzle {
  Dice dice[2][2][2];
  int num;
};

char buf[8][7];
int calc_array[5040][7];
int array_index = 0;

bool clearFLG;

void copyPuzzle(Puzzle &to, Puzzle from) {

  for (int h = 0; h < 2; h++) {
    for (int row = 0; row < 2; row++) {
      for (int col = 0; col < 2; col++) {
        to.dice[h][row][col].set(from.dice[h][row][col]);
      }
    }
  }
}

bool is_adj(char left, char right) {

  if (left > right) {
    swap(left, right);
  }

  return left + 32 == right;
}

void puzzle_calc(Puzzle puzzle) {

  if (puzzle.num == 8) {
    clearFLG = true;
    return;
  }

  switch (puzzle.num) {
  case 1:

    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[1][0][0]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][1][0].getNorth(), tmp_dice.getSouth()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[1][0][0].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 2:
    for (int i = 0; i <= 23; i++) {
      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[1][0][1]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][0][0].getEast(), tmp_dice.getWest()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[1][0][1].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 3:
    for (int i = 0; i <= 23; i++) {
      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[1][1][1]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][0][1].getSouth(), tmp_dice.getNorth()) ==
              false ||
          is_adj(puzzle.dice[1][1][0].getEast(), tmp_dice.getWest()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[1][1][1].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 4:
    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[0][1][0]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][1][0].getBottom(), tmp_dice.getTop()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[0][1][0].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 5:
    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[0][0][0]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][0][0].getBottom(), tmp_dice.getTop()) ==
              false ||
          is_adj(puzzle.dice[0][1][0].getNorth(), tmp_dice.getSouth()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[0][0][0].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 6:
    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[0][0][1]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][0][1].getBottom(), tmp_dice.getTop()) ==
              false ||
          is_adj(puzzle.dice[0][0][0].getEast(), tmp_dice.getWest()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[0][0][1].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 7:
    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[0][1][1]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][1][1].getBottom(), tmp_dice.getTop()) ==
              false ||
          is_adj(puzzle.dice[0][1][0].getEast(), tmp_dice.getWest()) == false ||
          is_adj(puzzle.dice[0][0][1].getSouth(), tmp_dice.getNorth()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[0][1][1].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  }
}

void func() {

  for (int i = 1; i <= 7; i++) {
    scanf("%s", buf[i]);
  }

  clearFLG = false;
  int calc_index = 0;

  while (clearFLG == false && calc_index < 5040) {

    Puzzle new_puzzle;
    new_puzzle.dice[1][1][0].setFirst(
        buf[0][0], buf[0][1], buf[0][2], buf[0][3], buf[0][4],
        buf[0][5]); //?????????S1?????????(1,1,0)????¨????

    for (int i = 0; i < 7; i++) {

      int num = calc_array[calc_index][i];

      switch (i) {
      case 0:
        new_puzzle.dice[1][0][0].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 1:
        new_puzzle.dice[1][0][1].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 2:
        new_puzzle.dice[1][1][1].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 3:
        new_puzzle.dice[0][1][0].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 4:
        new_puzzle.dice[0][0][0].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 5:
        new_puzzle.dice[0][0][1].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 6:
        new_puzzle.dice[0][1][1].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      }
    }

    for (int i = 0; i <= 23; i++) {
      Puzzle next_puzzle;
      copyPuzzle(next_puzzle, new_puzzle);
      next_puzzle.dice[1][1][0].setPos(i);
      next_puzzle.num = 1;
      puzzle_calc(next_puzzle);
    }

    calc_index++;
  }

  if (clearFLG) {
    printf("YES\\n");
  } else {
    printf("NO\\n");
  }
}

void recursive(bool check[8], int jyunretsu[7], int num) {

  if (num == 7) {
    for (int k = 0; k < 7; k++) {
      calc_array[array_index][k] = jyunretsu[k];
    }
    array_index++;
    return;
  }

  for (int i = 1; i <= 7; i++) {
    if (check[i] == false) {
      int next_jyunretsu[7];
      for (int k = 0; k < num; k++)
        next_jyunretsu[k] = jyunretsu[k];
      next_jyunretsu[num] = i;

      bool next_check[8];
      for (int k = 1; k <= 7; k++)
        next_check[k] = check[k];
      next_check[i] = true;

      recursive(next_check, next_jyunretsu, num + 1);
    }
  }
}

int main() {

  bool check[8];
  for (int i = 1; i <= 7; i++) {
    check[i] = false;
  }
  int jyunretsu[7];

  recursive(check, jyunretsu, 0);

  while (true) {
    scanf("%s", buf[0]);
    if (buf[0][0] == '0')
      break;

    func();
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

char order[25] = "NNNNWNNNWNNNENNNENNNWNNN";

class Dice {
public:
  void roll(char dst) {
    for (int i = 0; i < 6; i++)
      work[i] = words[i];
    switch (dst) {
    case 'E':
      setWords(work[3], work[1], work[0], work[5], work[4], work[2]);
      break;
    case 'S':
      setWords(work[1], work[5], work[2], work[3], work[0], work[4]);
      break;
    case 'N':
      setWords(work[4], work[0], work[2], work[3], work[5], work[1]);
      break;
    case 'W':
      setWords(work[2], work[1], work[5], work[0], work[4], work[3]);
      break;
    }
  };

  void setPos(int num) {
    for (int i = 0; i <= num; i++) {
      roll(order[i]);
    }
  }

  char getTop() { return words[0]; }

  char getEast() { return words[2]; }

  char getNorth() { return words[1]; }

  char getWest() { return words[3]; }

  char getBottom() { return words[5]; }

  char getSouth() { return words[4]; }

  void setWords(char w0, char w1, char w2, char w3, char w4, char w5) {
    words[0] = w0;
    words[1] = w1;
    words[2] = w2;
    words[3] = w3;
    words[4] = w4;
    words[5] = w5;
  }

  void setFirst(char c1, char c2, char c3, char c4, char c5, char c6) {
    words[0] = c1;
    words[1] = c5;
    words[2] = c3;
    words[3] = c4;
    words[4] = c2;
    words[5] = c6;
  }

  void set(Dice arg) {
    for (int i = 0; i < 6; i++) {
      words[i] = arg.words[i];
    }
  }

  char words[6];
  char work[6];
};

struct Puzzle {
  Dice dice[2][2][2];
  int num;
};

char buf[8][7];
int calc_array[5040][7];
int array_index = 0;

bool clearFLG;

void copyPuzzle(Puzzle &to, Puzzle from) {

  for (int h = 0; h < 2; h++) {
    for (int row = 0; row < 2; row++) {
      for (int col = 0; col < 2; col++) {
        to.dice[h][row][col].set(from.dice[h][row][col]);
      }
    }
  }
}

bool is_adj(char left, char right) {

  if (left > right) {
    swap(left, right);
  }

  return left + 32 == right;
}

void puzzle_calc(Puzzle puzzle) {

  if (puzzle.num == 8) {
    clearFLG = true;
    return;
  }

  switch (puzzle.num) {
  case 1:

    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[1][0][0]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][1][0].getNorth(), tmp_dice.getSouth()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[1][0][0].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 2:
    for (int i = 0; i <= 23; i++) {
      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[1][0][1]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][0][0].getEast(), tmp_dice.getWest()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[1][0][1].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 3:
    for (int i = 0; i <= 23; i++) {
      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[1][1][1]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][0][1].getSouth(), tmp_dice.getNorth()) ==
              false ||
          is_adj(puzzle.dice[1][1][0].getEast(), tmp_dice.getWest()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[1][1][1].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 4:
    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[0][1][0]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][1][0].getBottom(), tmp_dice.getTop()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[0][1][0].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 5:
    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[0][0][0]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][0][0].getBottom(), tmp_dice.getTop()) ==
              false ||
          is_adj(puzzle.dice[0][1][0].getNorth(), tmp_dice.getSouth()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[0][0][0].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 6:
    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[0][0][1]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][0][1].getBottom(), tmp_dice.getTop()) ==
              false ||
          is_adj(puzzle.dice[0][0][0].getEast(), tmp_dice.getWest()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[0][0][1].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  case 7:
    for (int i = 0; i <= 23; i++) {

      Dice tmp_dice;
      tmp_dice.set(puzzle.dice[0][1][1]);
      tmp_dice.setPos(i);

      if (is_adj(puzzle.dice[1][1][1].getBottom(), tmp_dice.getTop()) ==
              false ||
          is_adj(puzzle.dice[0][1][0].getEast(), tmp_dice.getWest()) == false ||
          is_adj(puzzle.dice[0][0][1].getSouth(), tmp_dice.getNorth()) == false)
        continue;

      Puzzle new_puzzle;
      copyPuzzle(new_puzzle, puzzle);

      new_puzzle.dice[0][1][1].setPos(i);

      new_puzzle.num = puzzle.num + 1;
      puzzle_calc(new_puzzle);
    }
    break;
  }
}

void func() {

  for (int i = 1; i <= 7; i++) {
    scanf("%s", buf[i]);
  }

  clearFLG = false;
  int calc_index = 0;

  while (clearFLG == false && calc_index < 5040) {

    Puzzle new_puzzle;
    new_puzzle.dice[1][1][0].setFirst(
        buf[0][0], buf[0][1], buf[0][2], buf[0][3], buf[0][4],
        buf[0][5]); //?????????S1?????????(1,1,0)????¨????

    for (int i = 0; i < 7; i++) {

      int num = calc_array[calc_index][i];

      switch (i) {
      case 0:
        new_puzzle.dice[1][0][0].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 1:
        new_puzzle.dice[1][0][1].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 2:
        new_puzzle.dice[1][1][1].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 3:
        new_puzzle.dice[0][1][0].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 4:
        new_puzzle.dice[0][0][0].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 5:
        new_puzzle.dice[0][0][1].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      case 6:
        new_puzzle.dice[0][1][1].setFirst(buf[num][0], buf[num][1], buf[num][2],
                                          buf[num][3], buf[num][4],
                                          buf[num][5]);
        break;
      }
    }

    for (int i = 0; i <= 23; i++) {
      Puzzle next_puzzle;
      copyPuzzle(next_puzzle, new_puzzle);
      next_puzzle.dice[1][1][0].setPos(i);
      next_puzzle.num = 1;
      puzzle_calc(next_puzzle);
    }

    calc_index++;
  }

  if (clearFLG) {
    printf("YES\\n");
  } else {
    printf("NO\\n");
  }
}

void recursive(bool check[8], int jyunretsu[7], int num) {

  if (num == 7) {
    for (int k = 0; k < 7; k++) {
      calc_array[array_index][k] = jyunretsu[k];
    }
    array_index++;
    return;
  }

  for (int i = 1; i <= 7; i++) {
    if (check[i] == false) {
      int next_jyunretsu[7];
      for (int k = 0; k < num; k++)
        next_jyunretsu[k] = jyunretsu[k];
      next_jyunretsu[num] = i;

      bool next_check[8];
      for (int k = 1; k <= 7; k++)
        next_check[k] = check[k];
      next_check[i] = true;

      recursive(next_check, next_jyunretsu, num + 1);
    }
  }
}

int main() {

  bool check[8];
  for (int i = 1; i <= 7; i++) {
    check[i] = false;
  }
  int jyunretsu[7];

  recursive(check, jyunretsu, 0);

  while (true) {
    scanf("%s", buf[0]);
    if (buf[0][0] == '0')
      break;

    func();
  }
  return 0;
}