Problem p01533 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef complex<double> P;
typedef pair<int, int> pii;
#define REP(i, n) for (ll i = 0; i < n; ++i)
#define REPR(i, n) for (ll i = 1; i < n; ++i)
#define FOR(i, a, b) for (ll i = a; i < b; ++i)

#define DEBUG(x) cout << #x << ": " << x << endl
#define DEBUG_VEC(v)                                                           \\
  cout << #v << ":";                                                           \\
  REP(i, v.size()) cout << " " << v[i];                                        \\
  cout << endl
#define ALL(a) (a).begin(), (a).end()

#define MOD (ll)(1e9 + 7)
#define ADD(a, b) a = ((a) + (b)) % MOD
#define FIX(a) ((a) % MOD + MOD) % MOD

#define INF 1e9

// splatoooooooooooooooooon

int masu[100][100];
int w, h;
int pos(int y, int x) { return y * w + x; }
int MAX_POS() { return pos(h - 1, w - 1) + 1; }
int getx(int p) { return p % w; }
int gety(int p) { return p / w; }

// struct vertex{int dst,pre;};
struct edge {
  int from, to, w;
};
bool operator<(const edge &e, const edge &f) {
  return e.w != f.w         ? e.w > f.w
         : e.from != f.from ? e.from < f.from
                            : e.to < f.to;
}
vi bf(vector<edge> es, int from) {
  vi dst(MAX_POS());
  REP(i, MAX_POS()) {
    if (i == from) {
      dst[i] = 0;
    } else {
      dst[i] = INF;
    }
  }
  REP(_, MAX_POS()) {
    REP(i, es.size()) {
      edge e = es[i];
      dst[e.to] = min(dst[e.to], dst[e.from] + e.w);
    }
  }
  return dst;
}

// http://www.prefield.com/algorithm/graph/dijkstra.html
vi dijkstra(vector<vector<edge>> g, int s) {
  vi dist(MAX_POS());
  int n = g.size();
  dist.assign(n, INF);
  dist[s] = 0;
  priority_queue<edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push((edge){-2, s, 0}); !Q.empty();) {
    edge e = Q.top();
    Q.pop();
    // if (prev[e.to] != -1) continue;
    REP(i, g[e.to].size()) {
      edge f = g[e.to][i];
      if (dist[f.to] > e.w + f.w) {
        dist[f.to] = e.w + f.w;
        Q.push((edge){f.from, f.to, e.w + f.w});
      }
    }
  }
  return dist;
}

int main() {
  cin >> w >> h;
  vector<string> mp(h);
  REP(i, h) cin >> mp[i];
  REP(i, h) REP(j, w) masu[i][j] = 1;
  int start, goal;
  vi ms;
  REP(i, h) REP(j, w) {
    if (mp[i][j] == '#') {
      // hole!
      FOR(y, -3, 4) FOR(x, -3, 4) {
        int ny = i + y;
        int nx = j + x;
        if (ny < 0 || nx < 0 || ny >= h || nx >= w)
          continue;
        masu[ny][nx] = max(masu[ny][nx], (int)(4 - max(abs(y), abs(x))));
      }
      masu[i][j] = INF;
    }
    if (mp[i][j] == 'S')
      start = pos(i, j);
    if (mp[i][j] == 'G')
      goal = pos(i, j);
    if (mp[i][j] == 'M')
      ms.push_back(pos(i, j));
  }

  vector<vector<edge>> es(MAX_POS());
  REP(i, h) REP(j, w) {
    if (i != 0) {
      es[pos(i, j)].push_back((edge){pos(i, j), pos(i - 1, j), masu[i][j]});
    }
    if (i != h - 1) {
      es[pos(i, j)].push_back((edge){pos(i, j), pos(i + 1, j), masu[i][j]});
    }
    if (j != 0) {
      es[pos(i, j)].push_back((edge){pos(i, j), pos(i, j - 1), masu[i][j]});
    }
    if (j != w - 1) {
      es[pos(i, j)].push_back((edge){pos(i, j), pos(i, j + 1), masu[i][j]});
    }
  }
  int cnt = 1 + 1 + ms.size();
  int kyori[cnt][cnt];
  REP(i, cnt) REP(j, cnt) kyori[i][j] = INF;
  REP(i, cnt) {
    vi ret;
    if (i == 0)
      ret = dijkstra(es, start);
    else if (i == cnt - 1)
      ret = dijkstra(es, goal);
    else
      ret = dijkstra(es, ms[i - 1]);
    REP(j, cnt) {
      if (j == i)
        continue;
      if (j == 0)
        kyori[i][j] = ret[start];
      else if (j == cnt - 1)
        kyori[i][j] = ret[goal];
      else
        kyori[i][j] = ret[ms[j - 1]];
    }
  }
  REP(k, cnt)
  REP(i, cnt) REP(j, cnt) kyori[i][j] =
      min(kyori[i][j], kyori[i][k] + kyori[k][j]);

  vi perm(cnt - 2);
  REP(i, cnt - 2) perm[i] = i + 1;
  int result = INF;
  do {
    int tmp = 0;
    tmp += kyori[0][perm[0]];
    REPR(i, cnt - 2) { tmp += kyori[perm[i - 1]][perm[i]]; }
    tmp += kyori[perm[cnt - 3]][cnt - 1];
    result = min(result, tmp);
  } while (next_permutation(ALL(perm)));
  cout << result << endl;
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef complex<double> P;
typedef pair<int, int> pii;
#define REP(i, n) for (ll i = 0; i < n; ++i)
#define REPR(i, n) for (ll i = 1; i < n; ++i)
#define FOR(i, a, b) for (ll i = a; i < b; ++i)

#define DEBUG(x) cout << #x << ": " << x << endl
#define DEBUG_VEC(v)                                                           \\
  cout << #v << ":";                                                           \\
  REP(i, v.size()) cout << " " << v[i];                                        \\
  cout << endl
#define ALL(a) (a).begin(), (a).end()

#define MOD (ll)(1e9 + 7)
#define ADD(a, b) a = ((a) + (b)) % MOD
#define FIX(a) ((a) % MOD + MOD) % MOD

#define INF 1e9

// splatoooooooooooooooooon

int masu[100][100];
int w, h;
int pos(int y, int x) { return y * w + x; }
int MAX_POS() { return pos(h - 1, w - 1) + 1; }
int getx(int p) { return p % w; }
int gety(int p) { return p / w; }

// struct vertex{int dst,pre;};
struct edge {
  int from, to, w;
};
vi bf(vector<edge> es, int from) {
  vi dst(MAX_POS());
  REP(i, MAX_POS()) {
    if (i == from) {
      dst[i] = 0;
    } else {
      dst[i] = INF;
    }
  }
  REP(_, MAX_POS()) {
    REP(i, es.size()) {
      edge e = es[i];
      dst[e.to] = min(dst[e.to], dst[e.from] + e.w);
    }
  }
  return dst;
}

int main() {
  cin >> w >> h;
  vector<string> mp(h);
  REP(i, h) cin >> mp[i];
  REP(i, h) REP(j, w) masu[i][j] = 1;
  int start, goal;
  vi ms;
  REP(i, h) REP(j, w) {
    if (mp[i][j] == '#') {
      // hole!
      FOR(y, -3, 4) FOR(x, -3, 4) {
        int ny = i + y;
        int nx = j + x;
        if (ny < 0 || nx < 0 || ny >= h || nx >= w)
          continue;
        masu[ny][nx] = max(masu[ny][nx], (int)(4 - max(abs(y), abs(x))));
      }
      masu[i][j] = INF;
    }
    if (mp[i][j] == 'S')
      start = pos(i, j);
    if (mp[i][j] == 'G')
      goal = pos(i, j);
    if (mp[i][j] == 'M')
      ms.push_back(pos(i, j));
  }

  vector<edge> es;
  REP(i, h) REP(j, w) {
    if (i != 0) {
      es.push_back((edge){pos(i, j), pos(i - 1, j), masu[i][j]});
    }
    if (i != h - 1) {
      es.push_back((edge){pos(i, j), pos(i + 1, j), masu[i][j]});
    }
    if (j != 0) {
      es.push_back((edge){pos(i, j), pos(i, j - 1), masu[i][j]});
    }
    if (j != w - 1) {
      es.push_back((edge){pos(i, j), pos(i, j + 1), masu[i][j]});
    }
  }
  int cnt = 1 + 1 + ms.size();
  int kyori[cnt][cnt];
  REP(i, cnt) REP(j, cnt) kyori[i][j] = INF;
  REP(i, cnt) {
    vi ret;
    if (i == 0)
      ret = bf(es, start);
    else if (i == cnt - 1)
      ret = bf(es, goal);
    else
      ret = bf(es, ms[i - 1]);
    REP(j, cnt) {
      if (j == i)
        continue;
      if (j == 0)
        kyori[i][j] = ret[start];
      else if (j == cnt - 1)
        kyori[i][j] = ret[goal];
      else
        kyori[i][j] = ret[ms[j - 1]];
    }
  }
  REP(k, cnt)
  REP(i, cnt) REP(j, cnt) kyori[i][j] =
      min(kyori[i][j], kyori[i][k] + kyori[k][j]);

  vi perm(cnt - 2);
  REP(i, cnt - 2) perm[i] = i + 1;
  int result = INF;
  do {
    int tmp = 0;
    tmp += kyori[0][perm[0]];
    REPR(i, cnt - 2) { tmp += kyori[perm[i - 1]][perm[i]]; }
    tmp += kyori[perm[cnt - 3]][cnt - 1];
    result = min(result, tmp);
  } while (next_permutation(ALL(perm)));
  cout << result << endl;
  return 0;
}