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

#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <queue>
#include <string>
#include <vector>
using namespace std;

#define INF 1e9

//????????????
class Timer {
  chrono::high_resolution_clock::time_point start, end;
  double limit;

public:
  Timer() { start = chrono::high_resolution_clock::now(); }
  Timer(double l) {
    start = chrono::high_resolution_clock::now();
    limit = l;
  }

  double getTime() {
    end = chrono::high_resolution_clock::now();
    return chrono::duration<double>(end - start).count();
  }

  bool Over() {
    if (getTime() > limit) {
      return true;
    }
    return false;
  }

  void setLimit(double l) { limit = l; }
  void setStart() { start = chrono::high_resolution_clock::now(); }
};

struct POINT {
  int x, y;

  POINT() {}
  POINT(int x_, int y_) { x = x_, y = y_; }

  bool operator<(const POINT &r) const { return x + y < r.x + r.y; }

  POINT operator+(const POINT &r) const { return POINT(x + r.x, y + r.y); }
};

struct STATUS {
  int dist;

  int id;
  vector<bool> used;

  STATUS() {}
  STATUS(int dist_, int id_, vector<bool> used_) {
    dist = dist_;
    id = id_;
    used = used_;
  }

  bool operator>(const STATUS &r) const { return dist > r.dist; }
};

int W, H;
vector<vector<int>> MAP;
int status[20][20];
int cost[20][20];
void dijkstra(POINT p) {
  int v[] = {-1, 0, 1, 0};
  int h[] = {0, 1, 0, -1};

  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      status[i][j] = 0;
      cost[i][j] = INF;
    }
  }
  cost[p.x][p.y] = 0;
  status[p.x][p.y] = 1;

  priority_queue<pair<int, POINT>, vector<pair<int, POINT>>,
                 greater<pair<int, POINT>>>
      U;
  U.push(make_pair(cost[p.x][p.y], p));
  while (!U.empty()) {
    //??¢?´¢???????????£??????????????§?????????????°???????
    POINT u = U.top().second;
    U.pop();

    if (status[u.x][u.y] == -1)
      continue;

    status[u.x][u.y] = -1;

    //?????????????°????????????¢???
    for (int i = 0; i < 4; i++) {
      POINT np = u + POINT(v[i], h[i]);
      if (np.x < 0 || np.x >= H || np.y < 0 || np.y >= W)
        continue;
      if (MAP[np.x][np.y] == 1)
        continue;
      if (status[np.x][np.y] != -1) {
        if (cost[np.x][np.y] > cost[u.x][u.y] + 1) {
          cost[np.x][np.y] = cost[u.x][u.y] + 1;
          status[np.x][np.y] = 1;
          U.push(make_pair(cost[np.x][np.y], np));
        }
      }
    }
  }
}

int main() {
  while (1) {
    cin >> W >> H;

    if (W == 0 && H == 0)
      break;

    MAP.assign(H, vector<int>(W, 0));

    vector<POINT> pos;
    int cnt = 0;

    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        char c;
        cin >> c;
        if (c == '*') {
          POINT p = POINT(i, j);
          pos.push_back(p);
          cnt++;
        } else if (c == 'x')
          MAP[i][j] = 1;
        else if (c == 'o') {
          POINT sp = POINT(i, j);
          pos.insert(pos.begin(), sp);
          cnt++;
        }
      }
    }

    bool fin = false;
    vector<vector<int>> dist(cnt);
    for (int i = 0; i < cnt; i++) {
      dist[i].resize(cnt);
      dijkstra(pos[i]);
      for (int j = 1; j < cnt; j++) {
        int distance = cost[pos[j].x][pos[j].y];
        if (distance == INF)
          fin = true;
        dist[i][j] = distance;
      }
    }

    if (fin) {
      cout << -1 << endl;
      continue;
    }

    Timer tmr(0.016);
    vector<priority_queue<STATUS, vector<STATUS>, greater<STATUS>>> STAT(cnt);
    STAT[0].push(STATUS(0, 0, vector<bool>(cnt)));
    while (1) {
      if (tmr.Over())
        break;

      for (int i = 0; i < cnt - 1; i++) {
        if (STAT[i].empty())
          continue;

        STATUS st = STAT[i].top();
        STAT[i].pop();

        for (int j = 1; j < cnt; j++) {
          if (st.used[j])
            continue;

          st.used[j] = true;
          STAT[i + 1].push(STATUS(st.dist + dist[st.id][j], j, st.used));
          st.used[j] = false;
        }
      }
    }

    STATUS last = STAT[cnt - 1].top();
    cout << last.dist << endl;
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <queue>
#include <string>
#include <vector>
using namespace std;

#define INF 1e9

//????????????
class Timer {
  chrono::high_resolution_clock::time_point start, end;
  double limit;

public:
  Timer() { start = chrono::high_resolution_clock::now(); }
  Timer(double l) {
    start = chrono::high_resolution_clock::now();
    limit = l;
  }

  double getTime() {
    end = chrono::high_resolution_clock::now();
    return chrono::duration<double>(end - start).count();
  }

  bool Over() {
    if (getTime() > limit) {
      return true;
    }
    return false;
  }

  void setLimit(double l) { limit = l; }
  void setStart() { start = chrono::high_resolution_clock::now(); }
};

struct POINT {
  int x, y;

  POINT() {}
  POINT(int x_, int y_) { x = x_, y = y_; }

  bool operator<(const POINT &r) const { return x + y < r.x + r.y; }

  POINT operator+(const POINT &r) const { return POINT(x + r.x, y + r.y); }
};

struct STATUS {
  int dist;

  int id;
  vector<bool> used;

  STATUS() {}
  STATUS(int dist_, int id_, vector<bool> used_) {
    dist = dist_;
    id = id_;
    used = used_;
  }

  bool operator>(const STATUS &r) const { return dist > r.dist; }
};

int W, H;
vector<vector<int>> MAP;
int status[20][20];
int cost[20][20];
void dijkstra(POINT p) {
  int v[] = {-1, 0, 1, 0};
  int h[] = {0, 1, 0, -1};

  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      status[i][j] = 0;
      cost[i][j] = INF;
    }
  }
  cost[p.x][p.y] = 0;
  status[p.x][p.y] = 1;

  priority_queue<pair<int, POINT>, vector<pair<int, POINT>>,
                 greater<pair<int, POINT>>>
      U;
  U.push(make_pair(cost[p.x][p.y], p));
  while (!U.empty()) {
    //??¢?´¢???????????£??????????????§?????????????°???????
    POINT u = U.top().second;
    U.pop();

    if (status[u.x][u.y] == -1)
      continue;

    status[u.x][u.y] = -1;

    //?????????????°????????????¢???
    for (int i = 0; i < 4; i++) {
      POINT np = u + POINT(v[i], h[i]);
      if (np.x < 0 || np.x >= H || np.y < 0 || np.y >= W)
        continue;
      if (MAP[np.x][np.y] == 1)
        continue;
      if (status[np.x][np.y] != -1) {
        if (cost[np.x][np.y] > cost[u.x][u.y] + 1) {
          cost[np.x][np.y] = cost[u.x][u.y] + 1;
          status[np.x][np.y] = 1;
          U.push(make_pair(cost[np.x][np.y], np));
        }
      }
    }
  }
}

int main() {
  while (1) {
    cin >> W >> H;

    if (W == 0 && H == 0)
      break;

    MAP.assign(H, vector<int>(W, 0));

    vector<POINT> pos;
    int cnt = 0;

    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        char c;
        cin >> c;
        if (c == '*') {
          POINT p = POINT(i, j);
          pos.push_back(p);
          cnt++;
        } else if (c == 'x')
          MAP[i][j] = 1;
        else if (c == 'o') {
          POINT sp = POINT(i, j);
          pos.insert(pos.begin(), sp);
          cnt++;
        }
      }
    }

    bool fin = false;
    vector<vector<int>> dist(cnt);
    for (int i = 0; i < cnt; i++) {
      dist[i].resize(cnt);
      dijkstra(pos[i]);
      for (int j = 1; j < cnt; j++) {
        int distance = cost[pos[j].x][pos[j].y];
        if (distance == INF)
          fin = true;
        dist[i][j] = distance;
      }
    }

    if (fin) {
      cout << -1 << endl;
      continue;
    }

    Timer tmr(0.5);
    vector<priority_queue<STATUS, vector<STATUS>, greater<STATUS>>> STAT(cnt);
    STAT[0].push(STATUS(0, 0, vector<bool>(cnt)));
    while (1) {
      if (tmr.Over())
        break;

      for (int i = 0; i < cnt - 1; i++) {
        if (STAT[i].empty())
          continue;

        STATUS st = STAT[i].top();
        STAT[i].pop();

        for (int j = 1; j < cnt; j++) {
          if (st.used[j])
            continue;

          st.used[j] = true;
          STAT[i + 1].push(STATUS(st.dist + dist[st.id][j], j, st.used));
          st.used[j] = false;
        }
      }
    }

    STATUS last = STAT[cnt - 1].top();
    cout << last.dist << endl;
  }

  return 0;
}