Problem p00190 (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;

struct Info {
  short table[5][5];
  int space_row1, space_col1, space_row2, space_col2;
};

map<string, bool> MAP;

bool rangeCheck(int row, int col) {
  if (row < 0 || row >= 5)
    return false;

  switch (row) {
  case 0:
    if (col == 2)
      return true;
    break;
  case 1:
    if (col >= 1 && col <= 3)
      return true;
    break;
  case 2:
    if (col >= 0 && col <= 4)
      return true;
    break;
  case 3:
    if (col >= 1 && col <= 3)
      return true;
    break;
  case 4:
    if (col == 2)
      return true;
    break;
  }
  return false;
}

bool clearFLG;
int ans;
int p[13];
int diff_row[4] = {-1, 0, 0, 1}, diff_col[4] = {0, -1, 1, 0};

void copyInfo(Info &to, Info from) {

  for (int row = 0; row <= 4; row++) {
    for (int col = 0; col <= 4; col++) {
      to.table[row][col] = from.table[row][col];
    }
  }
}

int calc_manhattan_sum(Info info) {

  int sum = 0;
  for (int row = 0; row <= 4; row++) {
    for (int col = 0; col <= 4; col++) {
      if (rangeCheck(row, col) == true && info.table[row][col] != 0) {
        switch (info.table[row][col]) {
        case 1:
          sum += abs(row - 1) + abs(col - 1);
          break;
        case 2:
          sum += abs(row - 1) + abs(col - 2);
          break;
        case 3:
          sum += abs(row - 1) + abs(col - 3);
          break;
        case 4:
          sum += abs(row - 2) + abs(col - 0);
          break;
        case 5:
          sum += abs(row - 2) + abs(col - 1);
          break;
        case 6:
          sum += abs(row - 2) + abs(col - 2);
          break;
        case 7:
          sum += abs(row - 2) + abs(col - 3);
          break;
        case 8:
          sum += abs(row - 2) + abs(col - 4);
          break;
        case 9:
          sum += abs(row - 3) + abs(col - 1);
          break;
        case 10:
          sum += abs(row - 3) + abs(col - 2);
          break;
        case 11:
          sum += abs(row - 3) + abs(col - 3);
          break;
        }
      }
    }
  }
  return sum;
}

void recursive(Info info, int depth, int max_depth) {

  if (clearFLG)
    return;

  if (depth == max_depth) {
    if (info.table[1][1] == 1 && info.table[1][2] == 2 &&
        info.table[1][3] == 3 && info.table[2][0] == 4 &&
        info.table[2][1] == 5 && info.table[2][2] == 6 &&
        info.table[2][3] == 7 && info.table[2][4] == 8 &&
        info.table[3][1] == 9 && info.table[3][2] == 10 &&
        info.table[3][3] == 11) {
      clearFLG = true;
    }
    return;
  }

  int adj_row, adj_col;

  for (int i = 0; i < 4; i++) {
    adj_row = info.space_row1 + diff_row[i];
    adj_col = info.space_col1 + diff_col[i];

    if (rangeCheck(adj_row, adj_col) == false ||
        info.table[adj_row][adj_col] == 0)
      continue;

    Info next_info;
    copyInfo(next_info, info);

    swap(next_info.table[info.space_row1][info.space_col1],
         next_info.table[adj_row][adj_col]);

    string tmp;
    for (int row = 0; row <= 4; row++) {
      for (int col = 0; col <= 4; col++) {
        if (rangeCheck(row, col)) {
          tmp.append(to_string(next_info.table[row][col]))
              .append(to_string('*'));
        }
      }
    }

    auto at = MAP.find(tmp);
    if (at != MAP.end())
      continue;

    MAP[tmp] = true;

    next_info.space_row1 = adj_row;
    next_info.space_col1 = adj_col;
    next_info.space_row2 = info.space_row2;
    next_info.space_col2 = info.space_col2;

    if (max_depth - (depth + 1) < calc_manhattan_sum(next_info))
      continue;

    recursive(next_info, depth + 1, max_depth);
  }

  for (int i = 0; i < 4; i++) {
    adj_row = info.space_row2 + diff_row[i];
    adj_col = info.space_col2 + diff_col[i];

    if (rangeCheck(adj_row, adj_col) == false ||
        info.table[adj_row][adj_col] == 0)
      continue;

    Info next_info;
    copyInfo(next_info, info);

    swap(next_info.table[info.space_row2][info.space_col2],
         next_info.table[adj_row][adj_col]);

    string tmp;
    for (int row = 0; row <= 4; row++) {
      for (int col = 0; col <= 4; col++) {
        if (rangeCheck(row, col)) {
          tmp.append(to_string(next_info.table[row][col]))
              .append(to_string('*'));
        }
      }
    }

    auto at = MAP.find(tmp);
    if (at != MAP.end())
      continue;

    MAP[tmp] = true;

    next_info.space_row1 = info.space_row1;
    next_info.space_col1 = info.space_col1;
    next_info.space_row2 = adj_row;
    next_info.space_col2 = adj_col;

    if (max_depth - (depth + 1) < calc_manhattan_sum(next_info))
      continue;

    recursive(next_info, depth + 1, max_depth);
  }
}

void func() {

  for (int i = 1; i < 13; i++)
    scanf("%d", &p[i]);

  Info first;
  first.table[0][2] = p[0];
  for (int i = 1; i <= 3; i++)
    first.table[1][i] = p[i];
  for (int i = 0; i <= 4; i++)
    first.table[2][i] = p[4 + i];
  for (int i = 1; i <= 3; i++)
    first.table[3][i] = p[8 + i];
  first.table[4][2] = p[12];

  int count = 0;

  for (int row = 0; row <= 4; row++) {
    for (int col = 0; col <= 4; col++) {
      if (rangeCheck(row, col) == true && first.table[row][col] == 0) {
        if (count == 0) {
          first.space_row1 = row;
          first.space_col1 = col;
          count++;
        } else {
          first.space_row2 = row;
          first.space_col2 = col;
        }
      }
    }
  }

  clearFLG = false;

  for (int max_depth = 0; max_depth <= 20; max_depth++) {
    MAP.clear();

    string tmp;
    for (int row = 0; row <= 4; row++) {
      for (int col = 0; col <= 4; col++) {
        if (rangeCheck(row, col)) {
          tmp.append(to_string(first.table[row][col])).append(to_string('*'));
        }
      }
    }

    MAP[tmp] = true;

    recursive(first, 0, max_depth);
    if (clearFLG) {
      ans = max_depth;
      break;
    }
  }

  if (clearFLG) {
    printf("%d\\n", ans);
  } else {
    printf("NA\\n");
  }
}

int main() {

  while (true) {
    scanf("%d", &p[0]);
    if (p[0] == -1)
      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;

struct Info {
  short table[5][5];
  int space_row1, space_col1, space_row2, space_col2;
};

map<string, bool> MAP;

bool rangeCheck(int row, int col) {
  if (row < 0 || row >= 5)
    return false;

  switch (row) {
  case 0:
    if (col == 2)
      return true;
    break;
  case 1:
    if (col >= 1 && col <= 3)
      return true;
    break;
  case 2:
    if (col >= 0 && col <= 4)
      return true;
    break;
  case 3:
    if (col >= 1 && col <= 3)
      return true;
    break;
  case 4:
    if (col == 2)
      return true;
    break;
  }
  return false;
}

bool clearFLG;
int ans;
int p[13];
int diff_row[4] = {-1, 0, 0, 1}, diff_col[4] = {0, -1, 1, 0};

void copyInfo(Info &to, Info from) {

  for (int row = 0; row <= 4; row++) {
    for (int col = 0; col <= 4; col++) {
      to.table[row][col] = from.table[row][col];
    }
  }
}

void recursive(Info info, int depth, int max_depth) {

  if (clearFLG)
    return;

  if (depth == max_depth) {
    if (info.table[1][1] == 1 && info.table[1][2] == 2 &&
        info.table[1][3] == 3 && info.table[2][0] == 4 &&
        info.table[2][1] == 5 && info.table[2][2] == 6 &&
        info.table[2][3] == 7 && info.table[2][4] == 8 &&
        info.table[3][1] == 9 && info.table[3][2] == 10 &&
        info.table[3][3] == 11) {
      clearFLG = true;
    }
    return;
  }

  int adj_row, adj_col;

  for (int i = 0; i < 4; i++) {
    adj_row = info.space_row1 + diff_row[i];
    adj_col = info.space_col1 + diff_col[i];

    if (rangeCheck(adj_row, adj_col) == false ||
        info.table[adj_row][adj_col] == 0)
      continue;

    Info next_info;
    copyInfo(next_info, info);

    swap(next_info.table[info.space_row1][info.space_col1],
         next_info.table[adj_row][adj_col]);

    string tmp;
    for (int row = 0; row <= 4; row++) {
      for (int col = 0; col <= 4; col++) {
        if (rangeCheck(row, col)) {
          tmp.append(to_string(next_info.table[row][col]))
              .append(to_string('*'));
        }
      }
    }

    auto at = MAP.find(tmp);
    if (at != MAP.end())
      continue;

    MAP[tmp] = true;

    next_info.space_row1 = adj_row;
    next_info.space_col1 = adj_col;
    next_info.space_row2 = info.space_row2;
    next_info.space_col2 = info.space_col2;

    recursive(next_info, depth + 1, max_depth);
  }

  for (int i = 0; i < 4; i++) {
    adj_row = info.space_row2 + diff_row[i];
    adj_col = info.space_col2 + diff_col[i];

    if (rangeCheck(adj_row, adj_col) == false ||
        info.table[adj_row][adj_col] == 0)
      continue;

    Info next_info;
    copyInfo(next_info, info);

    swap(next_info.table[info.space_row2][info.space_col2],
         next_info.table[adj_row][adj_col]);

    string tmp;
    for (int row = 0; row <= 4; row++) {
      for (int col = 0; col <= 4; col++) {
        if (rangeCheck(row, col)) {
          tmp.append(to_string(next_info.table[row][col]))
              .append(to_string('*'));
        }
      }
    }

    auto at = MAP.find(tmp);
    if (at != MAP.end())
      continue;

    MAP[tmp] = true;

    next_info.space_row1 = info.space_row1;
    next_info.space_col1 = info.space_col1;
    next_info.space_row2 = adj_row;
    next_info.space_col2 = adj_col;

    recursive(next_info, depth + 1, max_depth);
  }
}

void func() {

  for (int i = 1; i < 13; i++)
    scanf("%d", &p[i]);

  Info first;
  first.table[0][2] = p[0];
  for (int i = 1; i <= 3; i++)
    first.table[1][i] = p[i];
  for (int i = 0; i <= 4; i++)
    first.table[2][i] = p[4 + i];
  for (int i = 1; i <= 3; i++)
    first.table[3][i] = p[8 + i];
  first.table[4][2] = p[12];

  int count = 0;

  for (int row = 0; row <= 4; row++) {
    for (int col = 0; col <= 4; col++) {
      if (rangeCheck(row, col) == true && first.table[row][col] == 0) {
        if (count == 0) {
          first.space_row1 = row;
          first.space_col1 = col;
          count++;
        } else {
          first.space_row2 = row;
          first.space_col2 = col;
        }
      }
    }
  }

  clearFLG = false;

  for (int max_depth = 0; max_depth <= 20; max_depth++) {
    MAP.clear();

    string tmp;
    for (int row = 0; row <= 4; row++) {
      for (int col = 0; col <= 4; col++) {
        if (rangeCheck(row, col)) {
          tmp.append(to_string(first.table[row][col])).append(to_string('*'));
        }
      }
    }

    MAP[tmp] = true;

    recursive(first, 0, max_depth);
    if (clearFLG) {
      ans = max_depth;
      break;
    }
  }

  if (clearFLG) {
    printf("%d\\n", ans);
  } else {
    printf("NA\\n");
  }
}

int main() {

  while (true) {
    scanf("%d", &p[0]);
    if (p[0] == -1)
      break;

    func();
  }

  return 0;
}