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

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> p;
typedef vector<p> vp;
typedef tuple<int, int, int, vp> state;
#define rep(i, n) for (int i = 0; i < n; i++)
#define mp make_pair
#define mt make_tuple

map<state, int> dp;
vector<string> s;
int h, w;
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};

void makeWall() {
  string a = "";
  rep(i, s[0].size()) a += "#";
  s.insert(s.begin(), a);
  s.push_back(a);
  rep(i, s.size()) s[i] = "#" + s[i] + "#";
}

int solve(int x, int y, int k, vp used) {
  if (x == w && y == h && k == 0)
    return 0;
  state cur = mt(x, y, k, used);
  if (dp.find(cur) != dp.end())
    return dp[cur];
  int ret = INT_MIN;
  rep(d, 4) {
    int nx = x + dx[d];
    int ny = y + dy[d];
    int nk = k - (d > 1);
    if (nk < 0 || s[ny][nx] == '#')
      continue;
    vp nused;
    rep(i, used.size()) {
      if ((nx + ny) - (used[i].first + used[i].second) <= nk) {
        nused.push_back(used[i]);
      }
    }
    int val = 0;
    if (s[ny][nx] != '.') {
      auto it = lower_bound(nused.begin(), nused.end(), mp(nx, ny));
      if (it == nused.end() || *it != mp(nx, ny)) {
        val = s[ny][nx] - '0';
        nused.insert(it, mp(nx, ny));
      }
    }
    ret = max(ret, val + solve(nx, ny, nk, nused));
  }
  return dp[cur] = ret;
}

int main() {
  int k;
  cin >> h >> w >> k;
  s.resize(h);
  rep(i, h) cin >> s[i];
  makeWall();
  cout << solve(1, 1, k, vp()) << endl;
  return 0;
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

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

typedef pair<int, int> p;
typedef tuple<int, int, int, set<p>> mpdata;
typedef pair<int, mpdata> pqdata;
#define mt make_tuple
#define mp make_pair

map<mpdata, int> dp;
map<int, int> dist;

void check(int i, int k) {
  dist[i]--;
  if (dist[i] == 0)
    dist.erase(i);
  if (dist.begin()->first > i) {
    for (auto it : dp) {
      if (get<0>(it.first) + get<1>(it.first) < i - k) {
        dp.erase(it.first);
      }
    }
  }
}

int main() {
  int h, w, k;
  cin >> h >> w >> k;
  vector<string> s(h);
  rep(i, h) { cin >> s[i]; }

  priority_queue<pqdata> pq;
  pq.push(mp(-1, mt(0, 0, k, set<p>())));
  dp[mt(1, 0, k, set<p>())] = 0;
  dist[0]++;
  int ans = 1;

  while (!pq.empty()) {
    auto it = pq.top();
    pq.pop();
    int cost = -it.first;
    int y = get<0>(it.second);
    int x = get<1>(it.second);
    int use = get<2>(it.second);
    auto id = get<3>(it.second);

    if (cost < dp[mt(y, x, use, id)]) {
      check(y + x, k);
      continue;
    }

    if (x + 1 == w && y + 1 == h && use == 0) {
      ans = max(ans, cost);
      check(y + x, k);
      continue;
    }

    if (use > 0) {
      if (y > 0 && s[y - 1][x] != '#') {
        // up
        int nextcost = cost;
        auto nextid = id;
        if (s[y - 1][x] != '.' && id.find(mp(y - 1, x)) == id.end()) {
          nextid.insert(mp(y - 1, x));
          nextcost += s[y - 1][x] - '0';
        }
        auto t = mt(y - 1, x, use - 1, nextid);
        if (nextcost > dp[t]) {
          dp[t] = nextcost;
          pq.push(mp(-nextcost, t));
          dist[y + x - 1]++;
        }
      }

      if (x > 0 && s[y][x - 1] != '#') {
        // left
        int nextcost = cost;
        auto nextid = id;
        if (s[y][x - 1] != '.' && id.find(mp(y, x - 1)) == id.end()) {
          nextid.insert(mp(y, x - 1));
          nextcost += s[y][x - 1] - '0';
        }
        auto t = mt(y, x - 1, use - 1, nextid);
        if (nextcost > dp[t]) {
          dp[t] = nextcost;
          pq.push(mp(-nextcost, t));
          dist[y + x - 1]++;
        }
      }
    }

    if (y + 1 < h && s[y + 1][x] != '#') {
      // down
      int nextcost = cost;
      auto nextid = id;
      for (int i = x - use; i <= x + k - use; i++) {
        nextid.erase(mp(y - use, i));
      }
      if (s[y + 1][x] != '.' && nextid.find(mp(y + 1, x)) == nextid.end()) {
        nextid.insert(mp(y + 1, x));
        nextcost += s[y + 1][x] - '0';
      }
      auto t = mt(y + 1, x, use, nextid);
      if (dp[t] < nextcost) {
        dp[t] = nextcost;
        pq.push(mp(-nextcost, t));
        dist[y + x + 1]++;
      }
    }

    if (x + 1 < w && s[y][x + 1] != '#') {
      // right
      int nextcost = cost;
      auto nextid = id;
      for (int i = y - use; i <= y + k - use; i++) {
        nextid.erase(mp(i, x - use));
      }
      if (s[y][x + 1] != '.' && nextid.find(mp(y, x + 1)) == nextid.end()) {
        nextid.insert(mp(y, x + 1));
        nextcost += s[y][x + 1] - '0';
      }
      auto t = mt(y, x + 1, use, nextid);
      if (dp[t] < nextcost) {
        dp[t] = nextcost;
        pq.push(mp(-nextcost, t));
        dist[y + x + 1]++;
      }
    }
    check(y + x, k);
  }
  cout << ans - 1 << endl;
  return 0;
}