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

#include <algorithm>
#include <bitset>
#include <cctype>
#include <complex>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdio.h>
#include <string>
#include <vector>

#define VARIABLE(x) cerr << #x << "=" << x << endl
#define BINARY(x) static_cast<bitset<16>>(x)
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define REP(i, m, n) for (int i = m; i < (int)(n); i++)
#define if_range(x, y, w, h)                                                   \\
  if (0 <= (int)(x) && (int)(x) < (int)(w) && 0 <= (int)(y) &&                 \\
      (int)(y) < (int)(h))
#define ALL(a) (a).begin(), (a).end()
const int INF = 1e9;
// int dx[4]={0, 1, 0, -1}, dy[4]={-1, 0, 1, 0};
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;

/* struct P {
        int x, y, n;
        P(int n, int x, int y):n(n), x(x), y(y){}
        P(){}
 }; */

/** Problem2311 : Dessert Witch **/
enum {
  WHITE = 0,
  BLACK,
  NONE,
};

int board[8][8];
int board_tmp[8][8];

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

void print_board() {
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      if (board[j][i] == WHITE)
        cout << "o";
      else if (board[j][i] == BLACK)
        cout << "x";
      else
        cout << ".";
    }
    cout << endl;
  }
}

bool range_valid(int x, int y) {
  if (x < 0 || 8 <= x || y < 0 || 8 <= y)
    return false;
  return true;
}

bool can_reverse(int x, int y, int d, int turn) {
  if (!range_valid(x, y) || board[x][y] == NONE)
    return false;
  if (board[x][y] == turn)
    return true;

  return can_reverse(x + dx[d], y + dy[d], d, turn);
}

void do_reverse(int x, int y, int d, int turn) {
  if (board[x][y] == turn)
    return;
  board[x][y] = turn;
  do_reverse(x + dx[d], y + dy[d], d, turn);
}

bool can_put(int x, int y, int turn) {
  if (board[x][y] != NONE)
    return false;

  for (int i = 0; i < 8; i++) {
    int nx = x + dx[i], ny = y + dy[i];
    if (board[nx][ny] == 1 - turn && can_reverse(x + dx[i], y + dy[i], i, turn))
      return true;
  }
  return false;
}

bool can_put_all(int turn) {
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      if (can_put(j, i, turn))
        return true;
    }
  }
  return false;
}

bool gameover() { return !can_put_all(WHITE) && !can_put_all(BLACK); }

PII count_stone() {
  PII res = PII(0, 0);
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      if (board[i][j] == WHITE)
        res.first++;
      else if (board[i][j] == BLACK)
        res.second++;
    }
  }
  return res;
}

int main() {
  int turn = WHITE;

  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      char c;
      cin >> c;
      if (c == '.')
        board[j][i] = NONE;
      else if (c == 'o')
        board[j][i] = WHITE;
      else
        board[j][i] = BLACK;
    }
  }

  while (true) {
    if (gameover()) {
      print_board();
      break;
    }

    if (!can_put_all(turn)) {
      turn = 1 - turn;
      continue;
    }

    int target_x = -1, target_y = -1, cnt_max = 0;

    for (int y = 0; y < 8; y++) {
      for (int x = 0; x < 8; x++) {
        if (board[x][y] != NONE)
          continue;

        memcpy(board_tmp, board, sizeof(board));

        bool ok = false;
        for (int i = 0; i < 8; i++) {
          int nx = x + dx[i], ny = y + dy[i];
          if (board[nx][ny] != 1 - turn)
            continue;

          if (can_reverse(nx, ny, i, turn)) {
            do_reverse(nx, ny, i, turn);
            ok = true;
          }
        }

        if (ok) {
          board[x][y] = turn;
          PII cnt = count_stone();

          if (turn == WHITE) {
            if (cnt_max < cnt.first) {
              target_x = x;
              target_y = y;
              cnt_max = cnt.first;
            }
          } else {
            if (cnt_max <= cnt.second) {
              target_x = x;
              target_y = y;
              cnt_max = cnt.second;
            }
          }

          memcpy(board, board_tmp, sizeof(board));
        }
      }
    }

    for (int i = 0; i < 8; i++) {
      int nx = target_x + dx[i], ny = target_y + dy[i];
      if (board[nx][ny] != 1 - turn)
        continue;

      if (can_reverse(nx, ny, i, turn)) {
        do_reverse(nx, ny, i, turn);
      }
    }
    board[target_x][target_y] = turn;
    turn = 1 - turn;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cctype>
#include <complex>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <limits.h>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdio.h>
#include <string>
#include <vector>

#define VARIABLE(x) cerr << #x << "=" << x << endl
#define BINARY(x) static_cast<bitset<16>>(x)
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define REP(i, m, n) for (int i = m; i < (int)(n); i++)
#define if_range(x, y, w, h)                                                   \\
  if (0 <= (int)(x) && (int)(x) < (int)(w) && 0 <= (int)(y) &&                 \\
      (int)(y) < (int)(h))
#define ALL(a) (a).begin(), (a).end()
const int INF = 1e9;
// int dx[4]={0, 1, 0, -1}, dy[4]={-1, 0, 1, 0};
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;

/* struct P {
        int x, y, n;
        P(int n, int x, int y):n(n), x(x), y(y){}
        P(){}
 }; */

/** Problem2311 : Dessert Witch **/
enum {
  WHITE = 0,
  BLACK,
  NONE,
};

int board[8][8];
int board_tmp[8][8];

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

void print_board() {
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      if (board[j][i] == WHITE)
        cout << "o";
      else if (board[j][i] == BLACK)
        cout << "x";
      else
        cout << ".";
    }
    cout << endl;
  }
}

bool range_valid(int x, int y) {
  if (x < 0 || 8 <= x || y < 0 || 8 <= y)
    return false;
  return true;
}

bool can_reverse(int x, int y, int d, int turn) {
  if (!range_valid(x, y) || board[x][y] == NONE)
    return false;
  if (board[x][y] == turn)
    return true;

  return can_reverse(x + dx[d], y + dy[d], d, turn);
}

void do_reverse(int x, int y, int d, int turn) {
  if (board[x][y] == turn)
    return;
  board[x][y] = turn;
  do_reverse(x + dx[d], y + dy[d], d, turn);
}

bool can_put(int x, int y, int turn) {
  if (board[x][y] != NONE)
    return false;

  for (int i = 0; i < 8; i++) {
    int nx = x + dx[i], ny = y + dy[i];
    if (board[nx][ny] == 1 - turn && can_reverse(x + dx[i], y + dy[i], i, turn))
      return true;
  }
  return false;
}

bool can_put_all(int turn) {
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      if (can_put(j, i, turn))
        return true;
    }
  }
  return false;
}

bool gameover() { return !can_put_all(WHITE) && !can_put_all(BLACK); }

PII count_stone() {
  PII res = PII(0, 0);
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      if (board[i][j] == WHITE)
        res.first++;
      else if (board[i][j] == BLACK)
        res.second++;
    }
  }
  return res;
}

int main() {
  int turn = WHITE;

  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      char c;
      cin >> c;
      if (c == '.')
        board[j][i] = NONE;
      else if (c == 'o')
        board[j][i] = WHITE;
      else
        board[j][i] = BLACK;
    }
  }

  while (true) {
    if (!can_put_all(turn)) {
      turn = 1 - turn;
      continue;
    }

    int target_x = -1, target_y = -1, cnt_max = 0;

    for (int y = 0; y < 8; y++) {
      for (int x = 0; x < 8; x++) {
        if (board[x][y] != NONE)
          continue;

        memcpy(board_tmp, board, sizeof(board));

        bool ok = false;
        for (int i = 0; i < 8; i++) {
          int nx = x + dx[i], ny = y + dy[i];
          if (board[nx][ny] != 1 - turn)
            continue;

          if (can_reverse(nx, ny, i, turn)) {
            do_reverse(nx, ny, i, turn);
            ok = true;
          }
        }

        if (ok) {
          board[x][y] = turn;
          PII cnt = count_stone();

          if (turn == WHITE) {
            if (cnt_max < cnt.first) {
              target_x = x;
              target_y = y;
              cnt_max = cnt.first;
            }
          } else {
            if (cnt_max <= cnt.second) {
              target_x = x;
              target_y = y;
              cnt_max = cnt.second;
            }
          }

          memcpy(board, board_tmp, sizeof(board));
        }
      }
    }

    for (int i = 0; i < 8; i++) {
      int nx = target_x + dx[i], ny = target_y + dy[i];
      if (board[nx][ny] != 1 - turn)
        continue;

      if (can_reverse(nx, ny, i, turn)) {
        do_reverse(nx, ny, i, turn);
      }
    }
    board[target_x][target_y] = turn;
    turn = 1 - turn;

    if (gameover()) {
      print_board();
      break;
    }
  }
}