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

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

#define rep(i, n) for (int(i) = 0; (i) < (int)(n); ++(i))
#define foreach(c, i)                                                          \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)

const int kInf = 1 << 28;
struct edge {
  int to, cost, camp;
  bool operator<(const edge &other) const { return cost > other.cost; }
};
int N, M, C, S, G;
int P[22], Q[22][52], R[22][52], cost[22][10004];
int dis[22][102][102], d[102][22];
vector<edge> es[102];

void calc_cost() {
  for (int i = 0; i < C; ++i) {
    int k = 0, r = R[i][0];
    cost[i][0] = 0;
    for (int j = 1; j <= 10002; ++j) {
      cost[i][j] = cost[i][j - 1] + r;
      if (Q[i][k] == j) {
        r = R[i][k + 1];
        ++k;
      }
    }
  }
}

int get_cost(int camp, int dist) {
  if (dist <= 10002)
    return cost[camp][dist];
  return cost[camp][10002] + (dist - 10002) * R[camp][P[camp] - 1];
}

int calcost(int camp, int dist) {
  int t = lower_bound(Q[camp], Q[camp] + P[camp] - 1, dist) - Q[camp];
  if (t == 0) {
    // printf("[%d,%d] t = %d, ret = %d\\n", camp, dist, t, dist * R[camp][0]);
    return dist * R[camp][0];
  }
  int ret = R[camp][0] * Q[camp][0];
  for (int i = 1; i < t; ++i)
    ret += R[camp][i] * (Q[camp][i] - Q[camp][i - 1]);
  ret += R[camp][t] * (dist - Q[camp][t - 1]);
  // printf("[%d,%d] t = %d , ret = %d\\n", camp, dist, t, ret);
  return ret;
}

int solve() {
  // calc_cost();

  rep(c, C) rep(i, N) dis[c][i][i] = 0;
  rep(c, C) rep(k, N) rep(i, N) rep(j, N) {
    dis[c][i][j] = min(dis[c][i][j], dis[c][i][k] + dis[c][k][j]);
  }

  rep(i, N) es[i].clear();

  for (int c = 0; c < C; ++c) {
    for (int i = 0; i < N; ++i) {
      for (int j = i + 1; j < N; ++j) {
        if (dis[c][i][j] < kInf) {
          // int dd = get_cost(c, dis[c][i][j]);
          int dd = calcost(c, dis[c][i][j]);
          // printf("%d %d : %d\\n", i, j, dd);
          es[i].push_back((edge){j, dd, c});
          es[j].push_back((edge){i, dd, c});
        }
      }
    }
  }

  rep(i, N) rep(j, C) d[i][j] = kInf;
  priority_queue<edge> pq;
  d[S][20] = 0;
  pq.push((edge){S, 0, 20});
  while (!pq.empty()) {
    edge p = pq.top();
    pq.pop();
    int v = p.to;
    if (d[v][p.camp] < p.cost)
      continue;
    rep(i, es[v].size()) {
      edge e = es[v][i];
      if (p.camp == e.camp)
        continue;
      if (d[e.to][e.camp] > p.cost + e.cost) {
        d[e.to][e.camp] = p.cost + e.cost;
        pq.push((edge){e.to, d[e.to][e.camp], e.camp});
      }
    }
  }
  int ret = *min_element(d[G], d[G] + C);
  return ret != kInf ? ret : -1;
}

int main() {
  while (scanf("%d%d%d%d%d", &N, &M, &C, &S, &G), N | M) {
    --S;
    --G;

    rep(i, C) rep(j, N) rep(k, N) dis[i][j][k] = kInf;
    int x, y, d, c;
    rep(i, M) {
      scanf("%d%d%d%d", &x, &y, &d, &c);
      --x;
      --y;
      --c;
      dis[c][x][y] = min(dis[c][x][y], d);
      dis[c][y][x] = min(dis[c][y][x], d);
    }
    rep(i, C) scanf("%d", P + i);
    rep(i, C) {
      rep(j, P[i] - 1) scanf("%d", Q[i] + j);
      rep(j, P[i]) scanf("%d", R[i] + j);
    }
    printf("%d\\n", solve());
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#define rep(i, n) for (int(i) = 0; (i) < (int)(n); ++(i))
#define foreach(c, i)                                                          \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)

const int kInf = 1 << 28;
struct edge {
  int to, cost, camp;
};
int N, M, C, S, G;
vector<edge> es[202];
int cost[22][202], P[22], Q[22][52], R[22][52];

int dp[202][22][10002]; // 現在の頂点、利用した会社、連続して進んだ距離

struct State {
  int v, from, len, d;
  bool operator<(const State &other) const {
    if (d != other.d)
      return d > other.d;
    return v < other.v;
  }
};

void calc_cost() {
  for (int i = 0; i < C; ++i) {
    int k = 0, r = R[i][0];
    cost[i][0] = 0;
    for (int j = 1; j <= 200; ++j) {
      cost[i][j] = cost[i][j - 1] + r;
      if (Q[i][k] == j) {
        r = R[i][k + 1];
        ++k;
      }
    }
  }
}

int get_cost(int camp, int dist) {
  if (dist <= 200)
    return cost[camp][dist];
  return cost[camp][200] + (dist - 200) * R[camp][P[camp] - 1];
}

int solve() {
  calc_cost();

  rep(i, N) rep(j, C) fill(dp[i][j], dp[i][j] + 10002, kInf);
  rep(i, C) dp[S][i][0] = 0;

  priority_queue<State> pq;
  pq.push((State){S, 0, 0, 0});

  while (!pq.empty()) {
    State s = pq.top();
    pq.pop();
    int v = s.v, from = s.from;
    if (dp[v][from][s.len] < s.d)
      continue;
    rep(i, es[v].size()) {
      edge e = es[v][i];
      if (e.camp == from) {
        // int distance = s.d + cost[e.camp][e.cost + s.len] -
        // cost[e.camp][s.len];
        int next_d =
            s.d + get_cost(e.camp, e.cost + s.len) - get_cost(e.camp, s.len);
        int next_l = min(10001, e.cost + s.len);
        if (dp[e.to][e.camp][next_l] > next_d) {
          dp[e.to][e.camp][next_l] = next_d;
          pq.push((State){e.to, e.camp, s.len + e.cost, next_d});
        }

      } else {
        // int distance = cost[e.camp][e.cost] + s.d;
        int next_d = s.d + get_cost(e.camp, e.cost);
        if (dp[e.to][e.camp][e.cost] > next_d) {
          dp[e.to][e.camp][e.cost] = next_d;
          pq.push((State){e.to, e.camp, e.cost, next_d});
        }
      }
    }
  }

  int ans = kInf;
  rep(i, C) {
    rep(j, 10002) { ans = min(ans, dp[G][i][j]); }
  }
  if (ans == kInf)
    ans = -1;
  return ans;
}

int main() {
  while (cin >> N >> M >> C >> S >> G, N | M) {
    --S;
    --G;
    rep(i, N) es[i].clear();
    int x, y, d, c;
    rep(i, M) {
      cin >> x >> y >> d >> c;
      --x;
      --y;
      --c;
      es[x].push_back((edge){y, d, c});
      es[y].push_back((edge){x, d, c});
    }
    rep(i, C) cin >> P[i];
    rep(i, C) {
      rep(j, P[i] - 1) cin >> Q[i][j];
      rep(j, P[i]) cin >> R[i][j];
    }
    printf("%d\\n", solve());
  }
  return 0;
}