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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_M 1000000
#define PRIME_NUM MAX_M
#define SPIRAL_NUM 1003
#define DIR_FOUR 4  // dyとdxのための値
#define DIR_THREE 3 // udyとudxのための値

const int dy[4] = {-1, 0, 1, 0}, dx[4] = {0, 1, 0, -1}; // 上下左右4方向
const int udy[3] = {1, 1, 1}, udx[3] = {-1, 0, 1};      // 下3方向

int *primeNumber(int num) {
  int i, j, *ret;
  ret = (int *)malloc(sizeof(int) * (num + 1));
  for (i = 0; i <= num; i++)
    ret[i] = 1;
  ret[0] = ret[1] = 0;
  for (i = 2; i * i <= num; i++) {
    if (ret[i] == 1) {
      for (j = 2 * i; j <= num; j += i) {
        ret[j] = 0;
      }
    }
  }
  return ret;
}

int **spiralArray(int arg1,
                  int arg2) { // arg1 は2次元配列をつくるためのもの　arg2
                              // はどの値までスパイラルし続けるか
  int i, j, **ret, x, y, dir;
  ret = (int **)malloc(sizeof(int *) * arg1);
  for (i = 0; i < arg1; i++) {
    ret[i] = (int *)malloc(sizeof(int) * arg1);
  }
  for (i = 0; i < arg1; i++) {
    for (j = 0; j < arg1; j++) {
      ret[i][j] = -1;
    }
  }
  y = arg1 / 2;
  x = arg1 / 2 + 1;
  dir = 0; // dirの向きにまだ数字が設定されていなければdirの方向　そうでなければ(dir
           // + 1) % 4の方向
  ret[y][x - 1] = 1;
  ret[y][x] = 2;

  for (i = 3; i <= arg2; i++) {
    if (ret[y + dy[dir]][x + dx[dir]] == -1) {
      y += dy[dir];
      x += dx[dir];
      ret[y][x] = i;
      dir = (dir + (DIR_FOUR - 1)) % DIR_FOUR;
    } else {
      y += dy[(dir + 1) % DIR_FOUR];
      x += dx[(dir + 1) % DIR_FOUR];
      ret[y][x] = i;
    }
  }
  return ret;
}

int main(void) {
  int i, j, *pn, **sp, m, n, sx, sy, dp[SPIRAL_NUM][SPIRAL_NUM];
  pn = primeNumber(PRIME_NUM);
  sp = spiralArray(SPIRAL_NUM, PRIME_NUM);
  while (1) {
    scanf("%d%d", &m, &n);
    if (m == 0 && n == 0) {
      break;
    }

    // スタート地点の探索
    for (i = 0; i < SPIRAL_NUM; i++) {
      for (j = 0; j < SPIRAL_NUM; j++) {
        if (sp[i][j] == n) {
          sy = i;
          sx = j;
        }
      }
    }

    memset(dp, -1, sizeof(dp));
    dp[sy][sx] = 0;
    if (pn[n] == 1) {
      dp[sy][sx]++;
    }
    int y, x;
    for (y = 0; y < SPIRAL_NUM; y++) {
      for (x = 0; x < SPIRAL_NUM; x++) {
        for (i = 0; i < DIR_THREE; i++) {
          int ny = y + udy[i], nx = x + udx[i];
          if (ny < 0 || SPIRAL_NUM <= ny || nx < 0 || SPIRAL_NUM <= nx) {
            continue;
          }
          if (dp[y][x] != -1 && sp[ny][nx] != -1 && sp[ny][nx] <= m &&
              (dp[ny][nx] == -1 || dp[ny][nx] < dp[y][x] + 1 ||
               (dp[ny][nx] == dp[y][x] && pn[sp[ny][nx]] == 1))) {
            if (pn[sp[ny][nx]] == 1) {
              dp[ny][nx] = dp[y][x] + 1;
            } else {
              dp[ny][nx] = dp[y][x];
            }
          }
        }
      }
    }

    int ans1 = 0, ans2 = 0;
    ;
    for (i = 0; i < SPIRAL_NUM; i++) {
      for (j = 0; j < SPIRAL_NUM; j++) {
        if (pn[sp[i][j]] == 1 &&
            (ans1 < dp[i][j] || (ans1 == dp[i][j] && ans2 < sp[i][j]))) {
          ans1 = dp[i][j];
          ans2 = sp[i][j];
        }
      }
    }
    if (ans1 == 0) {
      printf("0 0\\n");
    } else {
      printf("%d %d\\n", ans1, ans2);
    }
    /*		for(i = 0;i < SPIRAL_NUM;i++){
                            for(j = 0;j < SPIRAL_NUM;j++){
                                    printf("%3d ",dp[i][j]);
                            }
                            printf("\\n");
                    }*/
  }
  free(pn);
  free(sp);
  return 0;
}

Error: MLE

Fixed submission:

#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <utility>
#define MAX_M 1000000
#define PRIME_NUM MAX_M
#define SPIRAL_NUM 1003
#define DIR_FOUR 4  // dyとdxのための値
#define DIR_THREE 3 // udyとudxのための値

using namespace std;

const int dy[4] = {-1, 0, 1, 0}, dx[4] = {0, 1, 0, -1}; // 上下左右4方向
const int udy[3] = {1, 1, 1}, udx[3] = {-1, 0, 1};      // 下3方向

int *primeNumber(int num) {
  int i, j, *ret;
  ret = (int *)malloc(sizeof(int) * (num + 1));
  for (i = 0; i <= num; i++)
    ret[i] = 1;
  ret[0] = ret[1] = 0;
  for (i = 2; i * i <= num; i++) {
    if (ret[i] == 1) {
      for (j = 2 * i; j <= num; j += i) {
        ret[j] = 0;
      }
    }
  }
  return ret;
}

int **spiralArray(int arg1,
                  int arg2) { // arg1 は2次元配列をつくるためのもの　arg2
                              // はどの値までスパイラルし続けるか
  int i, j, **ret, x, y, dir;
  ret = (int **)malloc(sizeof(int *) * arg1);
  for (i = 0; i < arg1; i++) {
    ret[i] = (int *)malloc(sizeof(int) * arg1);
  }
  for (i = 0; i < arg1; i++) {
    for (j = 0; j < arg1; j++) {
      ret[i][j] = -1;
    }
  }
  y = arg1 / 2;
  x = arg1 / 2 + 1;
  dir = 0; // dirの向きにまだ数字が設定されていなければdirの方向　そうでなければ(dir
           // + 1) % 4の方向
  ret[y][x - 1] = 1;
  ret[y][x] = 2;

  for (i = 3; i <= arg2; i++) {
    if (ret[y + dy[dir]][x + dx[dir]] == -1) {
      y += dy[dir];
      x += dx[dir];
      ret[y][x] = i;
      dir = (dir + (DIR_FOUR - 1)) % DIR_FOUR;
    } else {
      y += dy[(dir + 1) % DIR_FOUR];
      x += dx[(dir + 1) % DIR_FOUR];
      ret[y][x] = i;
    }
  }
  return ret;
}

int main(void) {
  int i, j, *pn, **sp, m, n, sx, sy, dp[SPIRAL_NUM][SPIRAL_NUM];
  pn = primeNumber(PRIME_NUM);
  sp = spiralArray(SPIRAL_NUM, PRIME_NUM);
  queue<pair<int, int>> que;
  while (1) {
    scanf("%d%d", &m, &n);
    if (m == 0 && n == 0) {
      break;
    }

    // スタート地点の探索
    for (i = 0; i < SPIRAL_NUM; i++) {
      for (j = 0; j < SPIRAL_NUM; j++) {
        if (sp[i][j] == n) {
          sy = i;
          sx = j;
        }
      }
    }

    memset(dp, -1, sizeof(dp));
    dp[sy][sx] = 0;
    if (pn[n] == 1) {
      dp[sy][sx]++;
    }
    // 幅優先探索でDP
    que.push(make_pair(sy, sx));
    while (que.size() != 0) {
      int y = que.front().first, x = que.front().second;
      que.pop();
      for (i = 0; i < DIR_THREE; i++) {
        int ny = y + udy[i], nx = x + udx[i];
        if (sp[ny][nx] != -1 && sp[ny][nx] <= m &&
            (dp[ny][nx] == -1 || dp[ny][nx] < dp[y][x] + 1 ||
             (dp[ny][nx] == dp[y][x] && pn[sp[ny][nx]] == 1))) {
          que.push(make_pair(ny, nx));
          if (pn[sp[ny][nx]] == 1) {
            dp[ny][nx] = dp[y][x] + 1;
          } else {
            dp[ny][nx] = dp[y][x];
          }
        }
      }
    }

    int ans1 = 0, ans2 = 0;
    ;
    for (i = 0; i < SPIRAL_NUM; i++) {
      for (j = 0; j < SPIRAL_NUM; j++) {
        if (pn[sp[i][j]] == 1 &&
            (ans1 < dp[i][j] || (ans1 == dp[i][j] && ans2 < sp[i][j]))) {
          ans1 = dp[i][j];
          ans2 = sp[i][j];
        }
      }
    }
    if (ans1 == 0) {
      printf("0 0\\n");
    } else {
      printf("%d %d\\n", ans1, ans2);
    }
  }
  return 0;
}