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


#include <algorithm>
#include <cmath>
#include <iostream>
#include <set>
#include <tuple>
#include <vector>
using namespace std;

const char NONE = '.';
const char START = 'S';
const char GOAL = 'G';

const int INF = 1000000000;

enum { ID, X, Y };
typedef tuple<int, int, int> Character;

enum { MOVE, SELECT };
typedef tuple<int, int> Result;

int x, y;
int n;
Character hero, rival;
vector<set<Character>> creature(5, set<Character>());

int cost(const Character &c1, const Character &c2) {
  return abs(get<X>(c1) - get<X>(c2)) + abs(get<Y>(c1) - get<Y>(c2));
}

Result solve() {
  Result result(INF, -1);
  for (int e = 0; e < 5; ++e) {
    vector<vector<int>> dp(5, vector<int>(n, INF));
    for (const auto &c : creature[(e + 1) % 5])
      dp[0][get<ID>(c)] = cost(hero, c);
    for (int i = 0; i < 3; ++i) {
      for (const auto &c1 : creature[(e + 1 + i) % 5]) {
        for (const auto &c2 : creature[(e + 2 + i) % 5]) {
          int v1 = get<ID>(c1);
          int v2 = get<ID>(c2);
          dp[i + 1][v2] = min(dp[i + 1][v2], dp[i][v1] + cost(c1, c2));
        }
      }
    }
    for (const auto &c : creature[(e + 4) % 5]) {
      int v1 = get<ID>(c);
      int v2 = get<ID>(rival);
      dp[4][v2] = min(dp[4][v2], dp[3][v1] + cost(c, rival));
    }
    int move = INF;
    for (const auto &d : dp[4])
      move = min(move, d);
    if (move < get<MOVE>(result))
      result = Result(move, e);
  }
  return result;
}

int main() {
  while (cin >> x >> y, x | y) {
    n = 0;
    for (auto &c : creature)
      c.clear();
    for (int i = 0; i < y; ++i) {
      string line;
      cin >> line;
      for (int j = 0; j < x; ++j) {
        if (line[j] == NONE)
          continue;
        else if (line[j] == START)
          hero = Character(n++, j, i);
        else if (line[j] == GOAL)
          rival = Character(n++, j, i);
        else
          creature[line[j] - '1'].insert(Character(n++, j, i));
      }
    }
    Result answer = solve();
    if (get<MOVE>(answer) == INF)
      cout << "NA" << endl;
    else
      cout << get<SELECT>(answer) + 1 << " " << get<MOVE>(answer) << endl;
  }
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <functional>
#include <iostream>
#include <queue>
#include <set>
#include <tuple>
#include <vector>
using namespace std;

const char NONE = '.';
const char START = 'S';
const char GOAL = 'G';

const int INF = 1000000000;

enum { ID, X, Y };
typedef tuple<int, int, int> Character;

enum { TO, WEIGHT };
typedef tuple<int, int> Edge;

enum { COST, VERTEX };
typedef tuple<int, int> Node;

enum { MOVE, SELECT };
typedef tuple<int, int> Result;

int x, y;
int n;
Character hero, rival;
set<Character> creature[5];

int Dijkstra(const vector<vector<int>> &matrix) {
  int start = get<ID>(hero);
  int goal = get<ID>(rival);
  set<int> visited;
  priority_queue<Node, vector<Node>, greater<Node>> q;
  q.push(Node(0, start));
  while (!q.empty()) {
    int from = get<VERTEX>(q.top());
    int cost = get<COST>(q.top());
    q.pop();
    if (from == goal)
      return cost;
    if (visited.count(from))
      continue;
    visited.insert(from);
    for (int to = 0; to < n; ++to) {
      if (visited.count(to))
        continue;
      q.push(Node(cost + matrix[from][to], to));
    }
  }
  return INF;
}

Result solve() {
  Result result(INF, -1);
  for (int e = 0; e < 5; ++e) {
    vector<vector<int>> matrix(n, vector<int>(n, INF));
    for (const auto &c : creature[(e + 1) % 5]) {
      int cost = abs(get<X>(c) - get<X>(hero)) + abs(get<Y>(c) - get<Y>(hero));
      matrix[get<ID>(hero)][get<ID>(c)] = cost;
    }
    for (const auto &c : creature[(e + 4) % 5]) {
      int cost =
          abs(get<X>(rival) - get<X>(c)) + abs(get<Y>(rival) - get<Y>(c));
      matrix[get<ID>(c)][get<ID>(rival)] = cost;
    }
    for (int i = 0; i < 3; ++i) {
      for (const auto &c1 : creature[(e + 1 + i) % 5]) {
        for (const auto &c2 : creature[(e + 2 + i) % 5]) {
          int cost =
              abs(get<X>(c2) - get<X>(c1)) + abs(get<Y>(c2) - get<Y>(c1));
          matrix[get<ID>(c1)][get<ID>(c2)] = cost;
        }
      }
    }
    int move = Dijkstra(matrix);
    if (move < get<MOVE>(result))
      result = Result(move, e);
  }
  return result;
}

int main() {
  while (cin >> x >> y, x | y) {
    n = 0;
    for (auto &c : creature)
      c.clear();
    for (int i = 0; i < y; ++i) {
      string line;
      cin >> line;
      for (int j = 0; j < x; ++j) {
        if (line[j] == NONE)
          continue;
        else if (line[j] == START)
          hero = Character(n++, j, i);
        else if (line[j] == GOAL)
          rival = Character(n++, j, i);
        else
          creature[line[j] - '1'].insert(Character(n++, j, i));
      }
    }
    Result answer = solve();
    if (get<MOVE>(answer) == INF)
      cout << "NA" << endl;
    else
      cout << get<SELECT>(answer) + 1 << " " << get<MOVE>(answer) << endl;
  }
}