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

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

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c) for (auto i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define INF (1 << 25)
typedef int Weight;
struct Edge {
  int src, dst;
  Weight cost;
  Weight capacity;
  Edge(int src, int dst, Weight capacity = 0, Weight cost = 0)
      : src(src), dst(dst), cost(cost), capacity(capacity) {}
};
bool operator<(const Edge &e, const Edge &f) {
  return e.cost != f.cost ? e.cost > f.cost : // !!INVERSE!!
             e.src != f.src ? e.src < f.src
                            : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

#define RESIDUE(u, v) (capacity[u][v] - flow[u][v])
#define RCOST(u, v) (cost[u][v] + h[u] - h[v])
pair<Weight, Weight> minimumCostFlow(const Graph &g, int s, int t) {
  const int n = g.size();
  Matrix capacity(n, Array(n)), cost(n, Array(n)), flow(n, Array(n));
  REP(u, n) FOR(e, g[u]) {
    capacity[e->src][e->dst] += e->capacity;
    cost[e->src][e->dst] += e->cost;
  }
  pair<Weight, Weight> total; // (cost, flow)
  vector<Weight> h(n);

  for (Weight F = INF; F > 0;) { // residual flow
    vector<Weight> d(n, INF);
    d[s] = 0;
    vector<int> p(n, -1);
    priority_queue<Edge> Q; // "e < f" <=> "e.cost > f.cost"
    for (Q.push(Edge(-2, s)); !Q.empty();) {
      Edge e = Q.top();
      Q.pop();
      if (p[e.dst] != -1)
        continue;
      p[e.dst] = e.src;
      FOR(f, g[e.dst]) if (RESIDUE(f->src, f->dst) > 0) {
        if (d[f->dst] > d[f->src] + RCOST(f->src, f->dst)) {
          d[f->dst] = d[f->src] + RCOST(f->src, f->dst);
          Q.push(Edge(f->src, f->dst, 0, d[f->dst]));
        }
      }
    }
    if (p[t] == -1)
      break;

    Weight f = F;
    for (int u = t; u != s; u = p[u])
      f = min(f, RESIDUE(p[u], u));
    for (int u = t; u != s; u = p[u]) {
      total.first += f * cost[p[u]][u];
      flow[p[u]][u] += f;
      flow[u][p[u]] -= f;
    }
    F -= f;
    total.second += f;
    REP(u, n) h[u] += d[u];
  }
  return total;
}

typedef int Part;

Part zero() { return 0; }

struct Condition {
  int day;
  int k;
  int l;
  int want;
};
bool operator<(const Condition &a, const Condition &b) {
  if (a.day != b.day)
    return a.day < b.day;
  if (a.k != b.k)
    return a.k < b.k;
  if (a.l != b.l)
    return a.l < b.l;
  return a.want < b.want;
}

int D, K, L;
int M, N, P;
int table[8][8];
int dp[6561][9][9][9];

int three[10] = {};
inline int get(int val, int pos) { return val / three[pos] % 3; }
inline int sub(int val, int pos) { return val - three[pos]; }
int dfs(Condition c) {
  if (c.l > L)
    return INF;
  if (c.k == K) {
    c.day++;
    c.k = 0;
    c.l = 0;
  }
  if (c.day == D) {
    return c.want == 0 ? 0 : INF;
  }
  int &res = dp[c.want][c.day][c.k][c.l];
  if (res != -1)
    return res;
  int ans = INF;
  // no choice
  ans = min(ans, dfs({c.day, c.k + 1, c.l, c.want}));
  if (c.k < K) {
    int exCost = 0;
    Part next = c.want;
    for (int k = 0; k < 2; k++) {
      if (get(next, c.k) >= 1) {
        next = sub(next, c.k);
        c.l++;
        exCost += table[c.day][c.k];
        ans = min(ans, dfs({c.day, c.k + 1, c.l, next}) + exCost);
      }
    }
    // two choice
  }
  return res = ans;
}

void addEdge(Graph &g, int a, int b, int cap, int cost) {
  g[a].push_back(Edge(a, b, cap, cost));
  g[b].push_back(Edge(b, a, 0, -cost));
}
int main() {
  three[0] = 1;
  for (int i = 1; i < 10; i++)
    three[i] = three[i - 1] * 3;
  while (cin >> D >> K >> L && D) {
    memset(dp, -1, sizeof(dp));
    for (int i = 0; i < D; i++)
      for (int j = 0; j < K; j++)
        cin >> table[i][j];
    cin >> M >> N >> P;
    vector<Part> r, p;

    for (int i = 0; i < M; i++) {
      Part t = 0;
      int wei = 1;
      for (int j = 0; j < K; j++) {
        int w;
        cin >> w;
        t += w * wei;
        wei *= 3;
      }
      r.push_back(t);
    }
    for (int i = 0; i < P; i++) {
      Part t = 0;
      int wei = 1;
      for (int j = 0; j < K; j++) {
        int w;
        cin >> w;
        t += w * wei;
        wei *= 3;
      }
      p.push_back(t);
    }
    int s = 0;
    int t = 1;
    Graph g(4 + M + P);
    int emp = g.size() - 1;
    int veryS = g.size() - 2;
    for (int i = 0; i < M; i++)
      addEdge(g, s, i + 2, 1, 0);
    for (int i = 0; i < M; i++) {
      for (int j = 0; j < P; j++) {
        vector<int> tmp;
        int a = r[i];
        int b = p[j];
        for (int k = 0; k < 8; k++) {
          if (a % 3 - b % 3 < 0)
            break;
          tmp.push_back(a % 3 - b % 3);
          a /= 3;
          b /= 3;
        }
        if (tmp.size() != 8)
          continue;
        int enc = 0;
        int wei = 1;
        for (int k = 0; k < tmp.size(); k++) {
          enc += tmp[k] * wei;
          wei *= 3;
        }
        Part rem = enc;

        int r = dfs({0, 0, 0, rem});
        if (r < INF) {
          addEdge(g, i + 2, 2 + M + j, 1, dfs({0, 0, 0, rem}));
        }
      }
      if (dfs({0, 0, 0, r[i]}) < INF)
        addEdge(g, i + 2, emp, 1, dfs({0, 0, 0, r[i]}));
    }
    for (int i = 0; i < P; i++)
      addEdge(g, 2 + M + i, t, 1, 0);
    addEdge(g, emp, t, N, 0);
    addEdge(g, veryS, s, N, 0);
    pair<int, int> res = minimumCostFlow(g, veryS, t);
    if (res.second != N)
      cout << -1 << endl;
    else
      cout << res.first << endl;

    // cout << dfs({0,0,0,{2,0}}) << endl;
  }
}

Error: MLE

Fixed submission:

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

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c) for (auto i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define INF (1 << 25)
typedef int Weight;
struct Edge {
  int src, dst;
  Weight cost;
  Weight capacity;
  Edge(int src, int dst, Weight capacity = 0, Weight cost = 0)
      : src(src), dst(dst), cost(cost), capacity(capacity) {}
};
bool operator<(const Edge &e, const Edge &f) {
  return e.cost != f.cost ? e.cost > f.cost : // !!INVERSE!!
             e.src != f.src ? e.src < f.src
                            : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

#define RESIDUE(u, v) (capacity[u][v] - flow[u][v])
#define RCOST(u, v) (cost[u][v] + h[u] - h[v])
pair<Weight, Weight> minimumCostFlow(const Graph &g, int s, int t) {
  const int n = g.size();
  Matrix capacity(n, Array(n)), cost(n, Array(n)), flow(n, Array(n));
  REP(u, n) FOR(e, g[u]) {
    capacity[e->src][e->dst] += e->capacity;
    cost[e->src][e->dst] += e->cost;
  }
  pair<Weight, Weight> total; // (cost, flow)
  vector<Weight> h(n);

  for (Weight F = INF; F > 0;) { // residual flow
    vector<Weight> d(n, INF);
    d[s] = 0;
    vector<int> p(n, -1);
    priority_queue<Edge> Q; // "e < f" <=> "e.cost > f.cost"
    for (Q.push(Edge(-2, s)); !Q.empty();) {
      Edge e = Q.top();
      Q.pop();
      if (p[e.dst] != -1)
        continue;
      p[e.dst] = e.src;
      FOR(f, g[e.dst]) if (RESIDUE(f->src, f->dst) > 0) {
        if (d[f->dst] > d[f->src] + RCOST(f->src, f->dst)) {
          d[f->dst] = d[f->src] + RCOST(f->src, f->dst);
          Q.push(Edge(f->src, f->dst, 0, d[f->dst]));
        }
      }
    }
    if (p[t] == -1)
      break;

    Weight f = F;
    for (int u = t; u != s; u = p[u])
      f = min(f, RESIDUE(p[u], u));
    for (int u = t; u != s; u = p[u]) {
      total.first += f * cost[p[u]][u];
      flow[p[u]][u] += f;
      flow[u][p[u]] -= f;
    }
    F -= f;
    total.second += f;
    REP(u, n) h[u] += d[u];
  }
  return total;
}

typedef array<char, 8> Part;

Part operator-(Part a, Part b) {
  for (int i = 0; i < 8; i++)
    a[i] -= b[i];
  return a;
}
Part zero() {
  Part zero;
  zero.fill(0);
  return zero;
}

struct Condition {
  int day;
  int k;
  int l;
  Part want;
};
bool operator<(const Condition &a, const Condition &b) {
  if (a.day != b.day)
    return a.day < b.day;
  if (a.k != b.k)
    return a.k < b.k;
  if (a.l != b.l)
    return a.l < b.l;
  return a.want < b.want;
}

int D, K, L;
int M, N, P;
int table[8][8];
map<Condition, int> dp;

int dfs(Condition c) {
  if (c.l > L)
    return INF;
  if (c.k == K) {
    c.day++;
    c.k = 0;
    c.l = 0;
  }
  if (c.day == D) {
    return zero() == c.want ? 0 : INF;
  }

  if (dp.count(c))
    return dp[c];

  Condition tmp = c;
  int ans = INF;
  // no choice
  ans = min(ans, dfs({c.day, c.k + 1, c.l, c.want}));
  if (c.k < K) {
    int exCost = 0;
    Part next = c.want;
    for (int k = 0; k < 2; k++) {
      if (next[c.k] >= 1) {
        next[c.k]--;
        c.l++;
        exCost += table[c.day][c.k];
        ans = min(ans, dfs({c.day, c.k + 1, c.l, next}) + exCost);
      }
    }
    // two choice
  }
  return dp[tmp] = ans;
}

int bad(Part p) {
  for (int i = 0; i < 8; i++)
    if (p[i] < 0)
      return true;
  return false;
}
void addEdge(Graph &g, int a, int b, int cap, int cost) {
  g[a].push_back(Edge(a, b, cap, cost));
  g[b].push_back(Edge(b, a, 0, -cost));
}
int main() {

  while (cin >> D >> K >> L && D) {
    dp.clear();
    for (int i = 0; i < D; i++)
      for (int j = 0; j < K; j++)
        cin >> table[i][j];
    cin >> M >> N >> P;
    vector<Part> r, p;

    for (int i = 0; i < M; i++) {
      Part t;
      t.fill(0);
      for (int j = 0; j < K; j++) {
        int w;
        cin >> w;
        t[j] = w;
      }
      r.push_back(t);
    }
    for (int i = 0; i < P; i++) {
      Part t;
      t.fill(0);
      for (int j = 0; j < K; j++) {
        int w;
        cin >> w;
        t[j] = w;
      }
      p.push_back(t);
    }
    int s = 0;
    int t = 1;
    Graph g(4 + M + P + 100);
    int emp = g.size() - 1;
    int veryS = g.size() - 2;
    for (int i = 0; i < M; i++)
      addEdge(g, s, i + 2, 1, 0);
    for (int i = 0; i < M; i++) {
      for (int j = 0; j < P; j++) {
        Part rem = r[i] - p[j];
        if (bad(rem))
          continue;

        int r = dfs({0, 0, 0, rem});
        if (r < INF) {
          addEdge(g, i + 2, 2 + M + j, 1, dfs({0, 0, 0, rem}));
        }
      }
      if (dfs({0, 0, 0, r[i]}) < INF)
        addEdge(g, i + 2, emp, 1, dfs({0, 0, 0, r[i]}));
    }
    for (int i = 0; i < P; i++)
      addEdge(g, 2 + M + i, t, 1, 0);
    addEdge(g, emp, t, N, 0);
    addEdge(g, veryS, s, N, 0);
    pair<int, int> res = minimumCostFlow(g, veryS, t);
    if (res.first >= INF || res.second != N)
      cout << -1 << endl;
    else
      cout << res.first << endl;

    // cout << dfs({0,0,0,{2,0}}) << endl;
  }
}