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

#include <iostream>
#include <map>
#include <tuple>
#include <vector>
using namespace std;

#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(i, n) REP(i, 0, n)

typedef pair<int, int> PII;

pair<int, bool> caves[1001][1001];
bool seive[2000001];

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

void make_seive(void) {
  for (int i = 0; i <= 2000000; i++) {
    seive[i] = true;
  }

  seive[0] = seive[1] = false;

  for (int i = 2; i * i <= 2000000; i++) {
    if (!seive[i])
      continue;
    for (int j = i * i; j <= 2000000; j += i) {
      seive[j] = false;
    }
  }
}

PII make_caves(int s, int n) {
  int x = s / 2;
  int y = s / 2;

  int cave_no = 1;
  int move_no = 0;
  int move_limit = 1;

  PII start_point;

  while (cave_no < s * s) {
    for (int i = 0; i < 2; i++) {

      for (int j = 0; j < move_limit; j++) {
        caves[y][x].first = cave_no;
        caves[y][x].second = seive[cave_no];

        if (cave_no == n) {
          start_point.first = x;
          start_point.second = y;
        }

        x += dx[move_no];
        y += dy[move_no];

        cave_no++;
      }

      move_no++;
      move_no %= 4;
    }

    move_limit++;
  }

  return start_point;
}

map<PII, pair<int, PII>> memo;

pair<int, PII> dfs(int x, int y, int s, int cave_no_limit) {
  if (memo.count(PII(x, y)))
    return memo[PII(x, y)];

  pair<int, PII> ret;
  ret.first = caves[y][x].second;
  ret.second = PII(x, y);

  pair<int, PII> max_route;
  max_route.first = 0;
  max_route.second = PII(-1, -1);

  for (int d = -1; d <= 1; d++) {
    if (x + d < 0 || x + d >= s || y + 1 < 0 || y + 1 >= s) {
      continue;
    }

    if (caves[y + 1][x + d].first > cave_no_limit) {
      continue;
    }

    pair<int, PII> route = dfs(x + d, y + 1, s, cave_no_limit);

    if (route.first == 0)
      continue;

    if (route.first > max_route.first)
      max_route = route;
    else if (route.first == max_route.first) {
      int rx = route.second.first;
      int ry = route.second.second;

      int mrx = max_route.second.first;
      int mry = max_route.second.second;

      if (caves[mry][mrx].first < caves[ry][rx].first) {
        max_route = route;
      }
    }
  }

  ret.first += max_route.first;
  if (max_route.first != 0) {
    ret.second = max_route.second;
  }

  return memo[PII(x, y)] = ret;
}

void dump_caves(int s, int x, int y) {
  for (int i = 0; i < s; i++) {
    for (int j = 0; j < s; j++) {
      char mark;
      if (j == x && i == y)
        mark = '!';
      else if (caves[i][j].second)
        mark = 'o';
      else
        mark = ' ';

      printf("%2d[%c] ", caves[i][j].first, mark);
    }
    printf("\\n");
  }
}

int main(void) {
  int m, n;
  make_seive();

  while (cin >> m >> n, m && n) {
    memo.clear();

    int s = 1;
    while (s * s < m)
      s += 2;

    int x, y;
    tie(x, y) = make_caves(s, n);

    pair<int, PII> res = dfs(x, y, s, m);

    int cnt = res.first;
    int cave_no = caves[res.second.second][res.second.first].first;

    if (cnt == 0)
      cave_no = 0;

    cout << cnt << " " << cave_no << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define INF (INT_MAX / 3)
#define PI (2 * acos(0.0))
#define EPS (1e-8)

typedef long long ll;
typedef unsigned long long ull;

int hw, m, n, sx, sy;
int cave[1001][1001];
int memo[1001][1001];
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, -1, 0, 1};
int length = 0, lastcave = 0;
bool isPrime[1000001];

void printCave() {
  for (int y = 0; y < hw; y++) {
    for (int x = 0; x < hw; x++) {
      printf("%02d ", cave[y][x]);
    }
    cout << endl;
  }
  cout << endl;
}

void init() {
  for (int i = 0; i <= 1000; i++) {
    for (int j = 0; j <= 1000; j++) {
      cave[i][j] = 0;
      memo[i][j] = -1;
    }
  }
}

void seive() {
  for (int i = 0; i <= 1000000; i++)
    isPrime[i] = true;

  isPrime[0] = isPrime[1] = false;
  for (int i = 2; i * i <= 1000000; i++) {
    for (int j = i * i; j <= 1000000; j += i)
      isPrime[j] = false;
  }
}

void buildCave(int num, int x, int y, int d) {
  cave[y][x] = num;
  if (num == m)
    return;
  int nx = x + dx[(d + 1) % 4], ny = y + dy[(d + 1) % 4];
  if (0 <= nx && nx < hw && 0 <= ny && ny < hw && cave[ny][nx] == 0)
    buildCave(num + 1, nx, ny, (d + 1) % 4);
  else
    buildCave(num + 1, x + dx[d], y + dy[d], d);
}

void solve(int x, int y, int cnt) {
  if (!isPrime[cave[y][x]])
    cnt--;

  if (cave[y][x] == 0)
    return;
  if (isPrime[cave[y][x]]) {
    if (cnt == length)
      lastcave = max(lastcave, cave[y][x]);
    else if (cnt > length)
      lastcave = cave[y][x];
    length = max(length, cnt);
  }

  if (0 <= x + 1 && x + 1 < hw && 0 <= y + 1 && y + 1 < hw)
    solve(x + 1, y + 1, cnt + 1);
  if (0 <= y + 1 && y + 1 < hw)
    solve(x, y + 1, cnt + 1);
  if (0 <= y + 1 && y + 1 < hw && 0 <= x - 1 && x - 1 < hw)
    solve(x - 1, y + 1, cnt + 1);
}

int main() {
  ios_base::sync_with_stdio(0);
  seive();
  while (cin >> m >> n && m != 0 && n != 0) {
    hw = int(ceil(sqrt(m)) / 2) * 2 + 1;
    init();
    lastcave = 0;
    length = 0;
    buildCave(1, hw / 2, hw / 2, -1);
    for (int i = 0; i < hw; i++) {
      for (int j = 0; j < hw; j++) {
        if (cave[i][j] == n) {
          sx = j;
          sy = i;
        }
      }
    }
    if (isPrime[cave[sy][sx]]) {
      length++;
      lastcave = n;
    }
    solve(sx, sy, 1);
    cout << length << " " << lastcave << endl;
  }
  return 0;
}