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

int H, W;
char table[20][21];

int dp[20][20][20][20];

int grundy(int row1, int col1, int row2, int col2) {

  if (row1 > row2 || col1 > col2)
    return 0;

  if (dp[row1][col1][row2][col2] != -1)
    return dp[row1][col1][row2][col2];

  set<int> S;

  for (int row = row1; row <= row2; row++) {
    for (int col = col1; col <= col2; col++) {
      if (table[row][col] == 'X')
        continue;

      int x = 0;
      x ^= grundy(row1, col1, row - 1, col - 1);
      x ^= grundy(row1, col + 1, row - 1, col2);
      x ^= grundy(row + 1, col1, row2, col - 1);
      x ^= grundy(row + 1, col + 1, row2, col2);
      S.insert(x);
    }
  }

  int g = 0;
  while (S.count(g) != 0)
    g++;

  return dp[row1][col1][row2][col2] = g;
}

int main() {

  scanf("%d %d", &H, &W);

  for (int row = 0; row < H; row++) {
    scanf("%s", table[row]);
  }

  for (int a = 0; a < H; a++) {
    for (int b = 0; b < W; b++) {
      for (int c = 0; c < H; c++) {
        for (int d = 0; d < W; d++) {
          dp[a][b][c][d] = -1;
        }
      }
    }
  }

  if (grundy(0, 0, H - 1, W - 1) != 0) {
    printf("First\\n");
  } else {
    printf("Second\\n");
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#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;

enum Turn {
  Sente,
  Gote,
};

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

struct Info {
  char table[20][21];
  vector<Data> V;
};

int H, W;

map<string, bool> MAP;

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

bool is_SenteWin(Info info, Turn turn) {

  if (turn == Sente) {

    for (int i = 0; i < info.V.size(); i++) {

      Info next_info;
      for (int row = 0; row < H; row++) {
        for (int col = 0; col < W; col++) {
          next_info.table[row][col] = info.table[row][col];
        }
      }

      next_info.table[info.V[i].row][info.V[i].col] = '#';

      for (int col = info.V[i].col - 1;
           rangeCheck(info.V[i].row, col) == true &&
           next_info.table[info.V[i].row][col] != '#';
           col--) {
        next_info.table[info.V[i].row][col] = '#';
      }

      for (int col = info.V[i].col + 1;
           rangeCheck(info.V[i].row, col) == true &&
           next_info.table[info.V[i].row][col] != '#';
           col++) {
        next_info.table[info.V[i].row][col] = '#';
      }

      for (int row = info.V[i].row - 1;
           rangeCheck(row, info.V[i].col) == true &&
           next_info.table[row][info.V[i].col] != '#';
           row--) {
        next_info.table[row][info.V[i].col] = '#';
      }

      for (int row = info.V[i].row + 1;
           rangeCheck(row, info.V[i].col) == true &&
           next_info.table[row][info.V[i].col] != '#';
           row++) {
        next_info.table[row][info.V[i].col] = '#';
      }

      for (int row = 0; row < H; row++) {
        for (int col = 0; col < W; col++) {
          if (next_info.table[row][col] == '.') {
            next_info.V.push_back(Data(row, col));
          }
        }
      }

      if (next_info.V.size() == 0)
        return true;

      //??¢????????£?????????????????????
      string tmp;

      for (int i = 0; i < next_info.V.size(); i++) {
        tmp.append(to_string(next_info.V[i].row));
        tmp.append(to_string(next_info.V[i].col));
      }

      auto at = MAP.find(tmp);
      if (at != MAP.end()) {
        if (MAP[tmp] == true) {
          return true;
        }
      }

      if ((MAP[tmp] = is_SenteWin(next_info, Gote)))
        return true;
    }

    return false;

  } else {

    for (int i = 0; i < info.V.size(); i++) {

      Info next_info;
      for (int row = 0; row < H; row++) {
        for (int col = 0; col < W; col++) {
          next_info.table[row][col] = info.table[row][col];
        }
      }

      next_info.table[info.V[i].row][info.V[i].col] = '#';

      for (int col = info.V[i].col - 1;
           rangeCheck(info.V[i].row, col) == true &&
           next_info.table[info.V[i].row][col] != '#';
           col--) {
        next_info.table[info.V[i].row][col] = '#';
      }

      for (int col = info.V[i].col + 1;
           rangeCheck(info.V[i].row, col) == true &&
           next_info.table[info.V[i].row][col] != '#';
           col++) {
        next_info.table[info.V[i].row][col] = '#';
      }

      for (int row = info.V[i].row - 1;
           rangeCheck(row, info.V[i].col) == true &&
           next_info.table[row][info.V[i].col] != '#';
           row--) {
        next_info.table[row][info.V[i].col] = '#';
      }

      for (int row = info.V[i].row + 1;
           rangeCheck(row, info.V[i].col) == true &&
           next_info.table[row][info.V[i].col] != '#';
           row++) {
        next_info.table[row][info.V[i].col] = '#';
      }

      for (int row = 0; row < H; row++) {
        for (int col = 0; col < W; col++) {
          if (next_info.table[row][col] == '.') {
            next_info.V.push_back(Data(row, col));
          }
        }
      }

      if (next_info.V.size() == 0)
        return false;

      //??¢????????£?????????????????????
      string tmp;

      for (int i = 0; i < next_info.V.size(); i++) {
        tmp.append(to_string(next_info.V[i].row));
        tmp.append(to_string(next_info.V[i].col));
      }

      auto at = MAP.find(tmp);
      if (at != MAP.end()) {
        if (MAP[tmp] == false) {
          return false;
        }
      }

      if (!(MAP[tmp] = is_SenteWin(next_info, Sente)))
        return false;
    }

    return true;
  }
}

int main() {

  scanf("%d %d", &H, &W);

  Info first;
  for (int row = 0; row < H; row++) {
    scanf("%s", first.table[row]);
    for (int col = 0; col < W; col++) {
      if (first.table[row][col] == '.') {
        first.V.push_back(Data(row, col));
      }
    }
  }

  if (is_SenteWin(first, Sente)) {
    printf("First\\n");
  } else {
    printf("Second\\n");
  }

  return 0;
}