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

#include <bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define SIZE 10

enum DIR { N, W, E, S };

enum Type {
  N_S,
  W_E,
  W_S,
  W_N,
  N_E,
  S_E,
  UNDEFINED,
};

struct LOC {
  LOC(int arg_row, int arg_col) {
    row = arg_row;
    col = arg_col;
  }
  int row, col;
};

bool FLG;
int h, w;
int first_row, first_col;
int diff_row[4] = {-1, 0, 0, 1}, diff_col[4] = {0, -1, 1, 0};
int base_map[SIZE][SIZE], rest[SIZE][SIZE];
int sum_rest; // 未確定出次の個数
Type table[SIZE][SIZE];
bool check[6][4] = {
    {true, false, false, true}, // N_S
    {false, true, true, false}, // W_E
    {false, true, false, true}, // W_S
    {true, true, false, false}, // W_N
    {true, false, true, false}, // N_E
    {false, false, true, true}  // S_E
};
Type type_array[7] = {N_S, W_E, W_S, W_N, N_E, S_E, UNDEFINED};
vector<LOC> V;

bool rangeCheck(int row, int col) {

  return row >= 0 && row <= h - 1 && col >= 0 && col <= w - 1;
}

void recursive(int row, int col) {

  if (FLG)
    return;

  if (row == h) {

    if (sum_rest == 0) {

      FLG = true;
    }

    return;
  }

  int next_row, next_col;
  if (col == w - 1) {

    next_row = row + 1;
    next_col = 0;
  } else {

    next_row = row;
    next_col = col + 1;
  }

  if (base_map[row][col] == 1) { // 石マス

    recursive(next_row, next_col);
    return;
  }

  // 空白マス

  if ((row != first_row || col != first_col) && sum_rest == 0) {
    return; // 非初セル&&未確定出次が残っていないなら閉路が発生しているはず
  }

  for (int i = 0; i < 6; i++) { // 配置パネルを走査
    int adj_row[2], adj_col[2];

    switch (type_array[i]) {
    case N_S:

      adj_row[0] = row - 1;
      adj_col[0] = col;

      adj_row[1] = row + 1;
      adj_col[1] = col;

      break;
    case W_E:

      adj_row[0] = row;
      adj_col[0] = col - 1;

      adj_row[1] = row;
      adj_col[1] = col + 1;

      break;
    case W_S:

      adj_row[0] = row;
      adj_col[0] = col - 1;

      adj_row[1] = row + 1;
      adj_col[1] = col;

      break;
    case W_N:

      adj_row[0] = row;
      adj_col[0] = col - 1;

      adj_row[1] = row - 1;
      adj_col[1] = col;

      break;
    case N_E:

      adj_row[0] = row - 1;
      adj_col[0] = col;

      adj_row[1] = row;
      adj_col[1] = col + 1;

      break;
    case S_E:

      adj_row[0] = row + 1;
      adj_col[0] = col;

      adj_row[1] = row;
      adj_col[1] = col + 1;

      break;
    }

    // 出次先が範囲外または石マスならSKIP
    if (!rangeCheck(adj_row[0], adj_col[0]) ||
        !rangeCheck(adj_row[1], adj_col[1]) ||
        (base_map[adj_row[0]][adj_col[0]] == 1) ||
        (base_map[adj_row[1]][adj_col[1]] == 1))
      continue;

    if (rangeCheck(row - 1, col) && check[table[row - 1][col]][S] &&
        !check[i][N])
      continue; // 上のS出次を満たせないなら刈る
    if (rangeCheck(row, col - 1) && check[table[row][col - 1]][E] &&
        !check[i][W])
      continue; // 左のE出次を満たせないなら刈る

    int rest_add = 0;   // sum_restに足した分
    int rest_minus = 0; // sum_restから引いた分
    bool is_OK = true;

    // パネルの整合性チェック
    switch (i) {
    case N_S: // N_S

      // 上のパネルのS
      if (!check[table[adj_row[0]][adj_col[0]]][S]) {

        is_OK = false;
      } else {

        // sum_restは変動なし
      }

      break;
    case W_E:

      // 左のパネルのE
      if (!check[table[adj_row[0]][adj_col[0]]][E]) {

        is_OK = false;
      } else {

        // sum_restは変動なし
      }

      break;
    case W_S:

      // 左のパネルのE
      if (!check[table[adj_row[0]][adj_col[0]]][E]) {

        is_OK = false;
      } else {

        // sum_restは変動なし
      }

      break;
    case W_N:

      // 左のパネルのEと上のパネルのS
      if (!check[table[adj_row[0]][adj_col[0]]][E] ||
          !check[table[adj_row[1]][adj_col[1]]][S]) {

        is_OK = false;
      } else {

        sum_rest -= 2;
        rest_minus = 2;
      }

      break;
    case N_E:

      // 上のパネルのS
      if (!check[table[adj_row[0]][adj_col[0]]][S]) {

        is_OK = false;
      } else {

        // sum_restは変動なし
      }

      break;
    case S_E: // S_E

      sum_rest += 2;
      rest_add = 2;

      break;
    }

    if (!is_OK) {

      continue;
    }

    table[row][col] = type_array[i];

    recursive(next_row, next_col);

    sum_rest -= rest_add;
    sum_rest += rest_minus;
  }
}

void func() {

  V.clear();
  first_row = -1;

  for (int row = 0; row < h; row++) {
    for (int col = 0; col < w; col++) {

      scanf("%d", &base_map[row][col]);
      if (base_map[row][col] == 0) {

        V.push_back(LOC(row, col));
        if (first_row == -1) {
          first_row = row;
          first_col = col;
        }
      }
    }
  }
  if (V.size() == 0) {

    printf("No\\n");
    return;
  }

  sum_rest = 0;
  FLG = false;

  for (int row = 0; row < h; row++) {
    for (int col = 0; col < w; col++) {

      table[row][col] = UNDEFINED;
    }
  }

  recursive(0, 0);

  if (FLG) {

    printf("Yes\\n");

  } else {

    printf("No\\n");
  }
}

int main() {

  while (true) {
    scanf("%d %d", &w, &h);
    if (h == 0 && w == 0)
      break;

    func();
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
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 {
  Info(int arg_row, int arg_col) {
    row = arg_row;
    col = arg_col;
  }
  int row, col;
};

int H, W, normal_area;
int num_GU, num_KI;
int diff_row[4] = {-1, 0, 0, 1}, diff_col[4] = {0, -1, 1, 0};
int boss[50], height[50];
int table[7][7];
bool used[7][7];

int get_boss(int id) {
  if (boss[id] == id)
    return id;
  else {
    return boss[id] = get_boss(boss[id]);
  }
}

void unite(int x, int y) {
  int boss_x = get_boss(x);
  int boss_y = get_boss(y);

  if (boss_x == boss_y)
    return;

  if (height[x] > height[y]) {

    boss[boss_y] = boss_x;

  } else if (height[x] < height[y]) {

    boss[boss_x] = boss_y;

  } else { // height[x] == height[y]

    boss[boss_y] = boss_x;
    height[x]++;
  }
}

int get_index(int row, int col) { return W * row + col; }

bool rangeCheck(int row, int col) {
  if (row >= 0 && row <= H - 1 && col >= 0 && col <= W - 1)
    return true;
  else {
    return false;
  }
}

bool FLG;

void recursive(int start_row, int start_col, int row, int col, int num) {

  if (FLG)
    return;

  if (normal_area - num < abs(start_row - row) + abs(start_col - col))
    return;

  int adj_row, adj_col;

  if (num ==
      normal_area) { // 全てのマスを網羅し、かつ、最後のマスがstart_row,start_colと隣接していればOK

    for (int i = 0; i < 4; i++) {
      adj_row = row + diff_row[i];
      adj_col = col + diff_col[i];

      if (adj_row == start_row && adj_col == start_col) {
        FLG = true;
        break;
      }
    }
    return;
  }

  for (int i = 0; i < 4; i++) {
    adj_row = row + diff_row[i];
    adj_col = col + diff_col[i];
    if (rangeCheck(adj_row, adj_col) == false || table[adj_row][adj_col] == 1 ||
        used[adj_row][adj_col] == true)
      continue;

    used[adj_row][adj_col] = true;
    recursive(start_row, start_col, adj_row, adj_col, num + 1);
    used[adj_row][adj_col] = false;
  }
}

void func() {

  int check = 0;

  for (int row = 0; row < H; row++) {
    for (int col = 0; col < W; col++) {
      scanf("%d", &table[row][col]);
      if (table[row][col] == 0)
        check++;
    }
  }

  if (check == 0) { // 全てのマスに石像
    printf("No\\n");
    return;
  }

  normal_area = check;

  for (int row = 0; row < H; row++) {
    for (int col = 0; col < W; col++)
      used[row][col] = false;
  }

  int adj_row, adj_col;
  queue<Info> Q;

  for (int row = 0; row < H; row++) {
    for (int col = 0; col < W; col++) {
      boss[get_index(row, col)] = get_index(row, col);
      height[get_index(row, col)] = 0;
    }
  }

  // 石像がないマスをuniteする
  for (int row = 0; row < H; row++) {
    for (int col = 0; col < W; col++) {
      if (used[row][col] == true || table[row][col] == 1)
        continue;

      used[row][col] = true;
      Q.push(Info(row, col));

      while (!Q.empty()) {

        for (int i = 0; i < 4; i++) {
          adj_row = Q.front().row + diff_row[i];
          adj_col = Q.front().col + diff_col[i];

          if (rangeCheck(adj_row, adj_col) == false ||
              table[adj_row][adj_col] == 1 || used[adj_row][adj_col] == true)
            continue;

          used[adj_row][adj_col] = true;
          unite(get_index(row, col), get_index(adj_row, adj_col));

          Q.push(Info(adj_row, adj_col));
        }
        Q.pop();
      }
    }
  }

  int area_num = 0;
  for (int row = 0; row < H; row++) {
    for (int col = 0; col < W; col++) {
      if (table[row][col] == 1)
        continue;

      if (get_index(row, col) == get_boss(get_index(row, col)))
        area_num++; // 石像のないマスのボスの個数を計上
    }
  }

  if (area_num != 1) {
    printf("No\\n");
    return;
  }

  for (int row = 0; row < H; row++) {
    for (int col = 0; col < W; col++)
      used[row][col] = false;
  }

  // ★閉路であるなら、どこから始めても良いはず★
  FLG = false;
  for (int start_row = 0; start_row < H; start_row++) {
    for (int start_col = 0; start_col < W; start_col++) {
      if (table[start_row][start_col] == 1)
        continue;

      used[start_row][start_col] = true;
      recursive(start_row, start_col, start_row, start_col, 1);

      if (FLG) {
        printf("Yes\\n");
      } else {
        printf("No\\n");
      }
      return;
    }
  }
}

int main() {

  while (true) {
    scanf("%d %d", &W, &H);
    if (W == 0 && H == 0)
      break;

    func();
  }

  return 0;
}