Problem p01493 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <algorithm>
#include <map>
#include <stdio.h>
using namespace std;
int UF[1010];
char str[1010][1010];
int FIND(int a) {
  if (UF[a] < 0)
    return a;
  return UF[a] = FIND(UF[a]);
}
void UNION(int a, int b) {
  a = FIND(a);
  b = FIND(b);
  if (a == b)
    return;
  UF[a] += UF[b];
  UF[b] = a;
}
int v;
int fi;
int dp[1010][1010][2];
int solve(int a, int b, int c) {
  if (~dp[a][b][c])
    return dp[a][b][c];
  int n = a + b;
  int used = (fi - n) + v;
  if (n == 2) {
    // printf("%d %d %d %d: %d\\n",a.p[0],a.p[1],a.p[2],a.p[3],!(t==used%2));
    if (used % 2 == c)
      return dp[a][b][c] = 0;
    return dp[a][b][c] = 1;
  }
  if (a && b && !solve(a - 1, b, c))
    return dp[a][b][c] = 1;
  if (a >= 2 && !solve(a - 1, b, c))
    return dp[a][b][c] = 1;
  if (b >= 2 && !solve(a + 1, b - 2, !c))
    return dp[a][b][c] = 1;

  //	printf("%d %d %d %d: 0\\n",a.p[0],a.p[1],a.p[2],a.p[3]);
  return dp[a][b][c] = 0;
}
int main() {
  int a;
  scanf("%d", &a);
  for (int i = 0; i < a; i++)
    scanf("%s", str[i]);
  for (int i = 0; i < a; i++)
    UF[i] = -1;
  for (int i = 0; i < a; i++)
    for (int j = 0; j < a; j++)
      if (str[i][j] == 'Y')
        UNION(i, j);
  for (int i = 0; i < a; i++)
    for (int j = i + 1; j < a; j++)
      if (str[i][j] == 'Y')
        v++;
  for (int i = 0; i < 1010; i++)
    for (int j = 0; j < 1010; j++)
      for (int k = 0; k < 2; k++)
        dp[i][j][k] = -1;
  int sa = 0;
  int sb = 0;
  int sc = 0;
  for (int i = 0; i < a; i++)
    if (UF[i] < 0) {
      int n = -UF[i];
      if (n & 2)
        sc = !sc;
      fi++;
      if (n % 2)
        sb++;
      else
        sa++;
    }
  if (solve(sa, sb, sc) == 1)
    printf("Taro\\n");
  else
    printf("Hanako\\n");
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <map>
#include <stdio.h>
using namespace std;
int UF[1010];
char str[1010][1010];
int FIND(int a) {
  if (UF[a] < 0)
    return a;
  return UF[a] = FIND(UF[a]);
}
void UNION(int a, int b) {
  a = FIND(a);
  b = FIND(b);
  if (a == b)
    return;
  UF[a] += UF[b];
  UF[b] = a;
}
int v;
int fi;
struct wolf {
  int p[4];
  wolf() { p[0] = p[1] = p[2] = p[3] = 0; }
};
inline bool operator<(const wolf &a, const wolf &b) {
  for (int i = 0; i < 4; i++)
    if (a.p[i] != b.p[i])
      return a.p[i] < b.p[i];
  return false;
}
map<wolf, int> dp;
int solve(wolf a) {
  if (dp.count(a))
    return dp[a];
  int n = 0;
  for (int i = 0; i < 4; i++)
    n += a.p[i];
  int used = (fi - n) + v;
  if (n == 2) {
    int t = (a.p[2] + a.p[3]) % 2;
    // printf("%d %d %d %d: %d\\n",a.p[0],a.p[1],a.p[2],a.p[3],!(t==used%2));
    if (used % 2 == t)
      return dp[a] = 0;
    return dp[a] = 1;
  }
  for (int i = 0; i < 4; i++)
    for (int j = i; j < 4; j++) {
      if (a.p[i] == 0 || a.p[j] == 0 || (i == j && a.p[i] == 1))
        continue;
      wolf to = a;
      to.p[i]--;
      to.p[j]--;
      to.p[(i + j) % 4]++;
      if (solve(to) == 0) {
        //		printf("%d %d %d %d: 1\\n",a.p[0],a.p[1],a.p[2],a.p[3]);
        return dp[a] = 1;
      }
    }
  //	printf("%d %d %d %d: 0\\n",a.p[0],a.p[1],a.p[2],a.p[3]);
  return dp[a] = 0;
}
int main() {
  int a;
  scanf("%d", &a);
  for (int i = 0; i < a; i++)
    scanf("%s", str[i]);
  for (int i = 0; i < a; i++)
    UF[i] = -1;
  for (int i = 0; i < a; i++)
    for (int j = 0; j < a; j++)
      if (str[i][j] == 'Y')
        UNION(i, j);
  for (int i = 0; i < a; i++)
    for (int j = i + 1; j < a; j++)
      if (str[i][j] == 'Y')
        v++;
  wolf s;
  for (int i = 0; i < a; i++)
    if (UF[i] < 0) {
      int n = -UF[i];
      fi++;
      s.p[n % 4]++;
    }
  if (solve(s) == 1)
    printf("Taro\\n");
  else
    printf("Hanako\\n");
}