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

#include <algorithm>
#include <bitset>
#include <iostream>
#include <queue>
#include <tuple>
#include <vector>
using namespace std;

const int NONE = -1;

const int DY[4] = {0, 1, 0, -1};
const int DX[4] = {1, 0, -1, 0};

enum { TIME, Y, X, BOUGHT };
typedef tuple<int, int, int, unsigned long> Vertex;

enum { GOODS, DISCOUNT, START, END };
typedef tuple<int, int, int, int> Sale;

int h, w;
int n;
vector<vector<int>> m;
vector<Sale> sale;

int sum(unsigned long bought) {
  int result = 0;
  bitset<8> b(bought);
  for (int i = 0; i < n; ++i)
    if (b[i])
      result += get<DISCOUNT>(sale[i]);
  return result;
}

int bfs(const Vertex &start) {
  int result = 0;
  vector<vector<vector<vector<int>>>> memo(
      101, vector<vector<vector<int>>>(
               h, vector<vector<int>>(w, vector<int>(1 << 8, -1))));
  queue<Vertex> q;
  q.push(start);

  while (!q.empty()) {
    int time = get<TIME>(q.front());
    int y = get<Y>(q.front());
    int x = get<X>(q.front());
    unsigned long bought = get<BOUGHT>(q.front());
    q.pop();

    if (time > 100)
      break;
    int cost = sum(bought);
    if (memo[time][y][x][bought] >= cost)
      continue;
    memo[time][y][x][bought] = cost;
    result = max(result, cost);

    for (int i = 0; i < 4; ++i) {
      int ny = y + DY[i];
      int nx = x + DX[i];
      if (ny < 0 || h <= ny || nx < 0 || w <= nx)
        continue;
      if (m[ny][nx] == NONE)
        continue;
      if (bought & (1 << m[ny][nx]))
        continue;
      for (int i = 0; i < n; ++i) {
        if (get<GOODS>(sale[i]) != m[ny][nx])
          continue;
        if (time < get<START>(sale[i]) || get<END>(sale[i]) <= time)
          continue;
        bought |= 1 << i;
      }
    }

    time += 1;
    for (int i = 0; i < 4; ++i) {
      int ny = y + DY[i];
      int nx = x + DX[i];
      if (ny < 0 || h <= ny || nx < 0 || w <= nx)
        continue;
      if (m[ny][nx] != NONE)
        continue;
      q.push(Vertex(time, ny, nx, bought));
    }
  }

  return result;
}

int main() {
  while (cin >> w >> h, w | h) {
    Vertex start;
    m = vector<vector<int>>(h, vector<int>(w, NONE));
    for (int i = 0; i < h; ++i)
      for (int j = 0; j < w; ++j) {
        char c;
        cin >> c;
        if (c == '.')
          continue;
        else if (c == 'P')
          start = Vertex(0, i, j, 0);
        else
          m[i][j] = c - '0';
      }

    sale.clear();
    cin >> n;
    for (int i = 0; i < n; ++i) {
      int g, d, s, e;
      cin >> g >> d >> s >> e;
      sale.push_back(Sale(g, d, s, e));
    }

    cout << bfs(start) << endl;
  }
}

Error: MLE

Fixed submission:


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

const int NONE = -1;

const int DY[4] = {0, 1, 0, -1};
const int DX[4] = {1, 0, -1, 0};

enum { TIME, Y, X, BOUGHT };
typedef tuple<int, int, int, unsigned long> Vertex;
enum { COST, VERTEX };
typedef tuple<int, Vertex> Node;

enum { GOODS, DISCOUNT, START, END };
typedef tuple<int, int, int, int> Sale;

int h, w;
vector<vector<int>> m;
vector<Sale> sale;

int bfs(const Vertex &start) {
  int result = 0;
  map<Vertex, int> memo;
  queue<Node> q;
  q.push(Node(0, start));
  while (!q.empty()) {
    int cost = get<COST>(q.front());
    Vertex v = get<VERTEX>(q.front());
    int time = get<TIME>(v);
    int y = get<Y>(v);
    int x = get<X>(v);
    unsigned long bought = get<BOUGHT>(v);
    q.pop();
    if (memo.count(v) && memo[v] >= cost)
      continue;
    memo[v] = cost;
    result = max(result, cost);
    if (time > 100)
      continue;
    for (int i = 0; i < 4; ++i) {
      int ny = y + DY[i];
      int nx = x + DX[i];
      if (ny < 0 || h <= ny || nx < 0 || w <= nx)
        continue;
      if (m[ny][nx] == NONE)
        continue;
      if (bought & (1 << m[ny][nx]))
        continue;
      for (const auto &s : sale) {
        if (get<GOODS>(s) != m[ny][nx])
          continue;
        if (time < get<START>(s) || get<END>(s) <= time)
          continue;
        bought |= 1 << m[ny][nx];
        cost += get<DISCOUNT>(s);
      }
    }
    time += 1;
    for (int i = 0; i < 4; ++i) {
      int ny = y + DY[i];
      int nx = x + DX[i];
      if (ny < 0 || h <= ny || nx < 0 || w <= nx)
        continue;
      if (m[ny][nx] != NONE)
        continue;
      q.push(Node(cost, Vertex(time, ny, nx, bought)));
    }
  }
  return result;
}

int main() {
  while (cin >> w >> h, w | h) {
    Vertex start;
    m = vector<vector<int>>(h, vector<int>(w, NONE));
    for (int i = 0; i < h; ++i)
      for (int j = 0; j < w; ++j) {
        char c;
        cin >> c;
        if (c == '.')
          continue;
        else if (c == 'P')
          start = Vertex(0, i, j, 0);
        else
          m[i][j] = c - '0';
      }

    sale.clear();
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
      int g, d, s, e;
      cin >> g >> d >> s >> e;
      sale.push_back(Sale(g, d, s, e));
    }

    cout << bfs(start) << endl;
  }
}