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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

#define INF (1 << 29)
#define MAX 55

typedef pair<int, int> P;

int N, D;
int cost[MAX][MAX];
P dp[MAX][MAX]; // dp[何泊目][泊まってるホテル] := (宿泊代の合計, 移動回数)

bool isValid(int p, int m, vector<int> path) {
  int sum = 0;
  int move = 0;
  for (int i = 0; i < (int)path.size(); i++)
    sum += cost[i][path[i]];
  for (int i = 1; i < (int)path.size(); i++) {
    if (path[i] != path[i - 1])
      move++;
  }
  if (p == sum && move == m)
    return true;
  else
    return false;
}

int main() {
  cin >> N >> D;
  for (int i = 0; i < N; i++)
    for (int j = 0; j < D; j++)
      cin >> cost[j][i];

  for (int i = 0; i < MAX; i++)
    for (int j = 0; j < MAX; j++)
      dp[i][j].first = dp[i][j].second = INF;

  vector<int> paths[MAX][MAX];
  for (int j = 0; j < N; j++) {
    dp[0][j] = P(cost[0][j], 0);
    vector<int> p;
    paths[0][j].push_back(j);
  }

  for (int i = 1; i < D; i++) {
    for (int k = 0; k < N; k++) {
      for (int j = 0; j < N; j++) {

        P next = dp[i - 1][k];
        next.first += cost[i][j];
        if (j != k)
          next.second += 1;

        vector<int> path;
        path = paths[i - 1][k];
        path.push_back(j);

        if (dp[i][j] >= next) {
          dp[i][j] = min(dp[i][j], next);
          paths[i][j] = path;
        }
      }
    }
  }

  for (int i = 1; i < D; i++) {
    for (int k = N - 1; k >= 0; k--) {
      for (int j = N - 1; j >= 0; j--) {

        P next = dp[i - 1][k];
        next.first += cost[i][j];
        if (j != k)
          next.second += 1;

        vector<int> path;
        path = paths[i - 1][k];
        path.push_back(j);

        if (dp[i][j] >= next) {
          dp[i][j] = min(dp[i][j], next);
          paths[i][j] = min(paths[i][j], path);
        }
      }
    }
  }

  for (int i = 1; i < D; i++) {
    for (int k = 0; k < N; k++) {
      for (int j = 0; j < N; j++) {

        P next = dp[i - 1][k];
        next.first += cost[i][j];
        if (j != k)
          next.second += 1;

        vector<int> path;
        path = paths[i - 1][k];
        path.push_back(j);

        if (dp[i][j] >= next) {
          dp[i][j] = min(dp[i][j], next);
          paths[i][j] = min(paths[i][j], path);
        }
      }
    }
  }

  /*
  for(int i = 0 ; i < D ; i++){
    for(int j = 0 ; j < N ; j++){
      cout << " (" << dp[i][j].first << ", " << dp[i][j].second << ") ";
    }
    cout << endl;
  }
*/
  P ans;
  ans.first = ans.second = INF;
  for (int j = 0; j < N; j++)
    ans = min(ans, dp[D - 1][j]);

  cout << ans.first << ' ' << ans.second << endl;

  vector<int> ans_path;

  for (int j = 0; j < N; j++) {
    if (dp[D - 1][j] == ans) {
      if (!isValid(ans.first, ans.second, paths[D - 1][j]))
        continue;
      if (ans_path.size() == 0)
        ans_path = paths[D - 1][j];
      else
        ans_path = min(ans_path, paths[D - 1][j]);
    }
  }

  if (ans_path.size() == 0)
    assert(false);
  for (int i = 0; i < ans_path.size(); i++) {
    cout << ans_path[i] + 1 << endl;
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

#define INF (1 << 29)
#define MAX 55

typedef pair<int, int> P;

int N, D;
int cost[MAX][MAX];
P dp[MAX][MAX]; // dp[何泊目][泊まってるホテル] := (宿泊代の合計, 移動回数)

bool isValid(int p, int m, vector<int> path) {
  int sum = 0;
  int move = 0;
  for (int i = 0; i < (int)path.size(); i++)
    sum += cost[i][path[i]];
  for (int i = 1; i < (int)path.size(); i++) {
    if (path[i] != path[i - 1])
      move++;
  }
  if (p == sum && move == m)
    return true;
  else
    return false;
}

int main() {
  cin >> N >> D;
  for (int i = 0; i < N; i++)
    for (int j = 0; j < D; j++)
      cin >> cost[j][i];

  for (int i = 0; i < MAX; i++)
    for (int j = 0; j < MAX; j++)
      dp[i][j].first = dp[i][j].second = INF;

  vector<vector<int>> paths[MAX][MAX];
  for (int j = 0; j < N; j++) {
    dp[0][j] = P(cost[0][j], 0);
    vector<int> p;
    p.push_back(j);
    paths[0][j].push_back(p);
  }

  for (int i = 1; i < D; i++) {
    for (int j = N - 1; j >= 0; j--) {
      for (int k = N - 1; k >= 0; k--) {
        P next = dp[i - 1][k];
        next.first += cost[i][j];
        if (j != k)
          next.second += 1;

        for (int p = 0; p < paths[i - 1][k].size(); p++) {
          vector<int> path;
          path = paths[i - 1][k][p];
          path.push_back(j);

          if (dp[i][j] >= next) {
            dp[i][j] = min(dp[i][j], next);
            paths[i][j].push_back(path);
          }
        }
      }
    }
  }

  /*
  for(int i = 0 ; i < D ; i++){
    for(int j = 0 ; j < N ; j++){
      cout << " (" << dp[i][j].first << ", " << dp[i][j].second << ") ";
    }
    cout << endl;
  }
*/
  P ans;
  ans.first = ans.second = INF;
  for (int j = 0; j < N; j++)
    ans = min(ans, dp[D - 1][j]);

  cout << ans.first << ' ' << ans.second << endl;
  /*
  for(int i = 0 ; i < paths[D-1][2].size() ; i++){
    vector<int> p = paths[D-1][0][i];
    for(int j = 0 ; j < p.size() ; j++){
      cout << p[j] << endl;
    }
    cout << endl;
  }
  */
  vector<int> ans_path;

  for (int j = 0; j < N; j++) {
    if (dp[D - 1][j] == ans) {
      for (int k = 0; k < paths[D - 1][j].size(); k++) {
        if (!isValid(ans.first, ans.second, paths[D - 1][j][k]))
          continue;
        if (ans_path.size() == 0)
          ans_path = paths[D - 1][j][k];
        else
          ans_path = min(ans_path, paths[D - 1][j][k]);
      }
    }
  }
  // reverse(ans_path.begin(), ans_path.end());

  for (int i = 0; i < ans_path.size(); i++) {
    cout << ans_path[i] + 1 << endl;
  }
  return 0;
}