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

// 基本テンプレート

#include <algorithm>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

#define rep(i, a, n) for (int(i) = (a); (i) < (n); (i)++)
#define repq(i, a, n) for (int(i) = (a); (i) <= (n); (i)++)
#define repr(i, a, n) for (int(i) = (a); (i) >= (n); (i)--)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define int long long int

template <typename T> void chmax(T &a, T b) { a = max(a, b); }
template <typename T> void chmin(T &a, T b) { a = min(a, b); }
template <typename T> void chadd(T &a, T b) { a = a + b; }

typedef pair<int, int> pii;
typedef long long ll;

int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const ll INF = 1001001001001001LL;
const ll MOD = 1000000007LL;

char board[30][30];
int H, W, disc[10][105], rec[20][20][105][1 << 8];

struct Elem {
  int x, y, time, bit, cost;
  bool operator<(const Elem &e) const { return cost < e.cost; }
};

signed main() {
  while (cin >> W >> H, H || W) {
    memset(disc, 0, sizeof(disc));
    memset(rec, -1, sizeof(rec));
    int sx = -1, sy = -1;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        cin >> board[i][j];
        if (board[i][j] == 'P')
          sx = i, sy = j;
      }
    }

    int N, lim = 0, ans = 0;
    cin >> N;
    vector<int> comp(10, -1);
    for (int i = 0; i < N; i++) {
      int g, d, s, e;
      cin >> g >> d >> s >> e;
      comp[g]++;
      chmax(lim, e + 1);
      for (int k = s; k < e; k++) {
        chmax(disc[g][k], d);
      }
    }

    // ざあつ
    int id = 0;
    for (auto &x : comp) {
      if (x >= 0)
        x = id++;
    }
    vector<int> inv(id);
    for (int i = 0; i < 10; i++) {
      if (comp[i] < 0)
        continue;
      inv[comp[i]] = i;
    }

    // cand の部分集合
    vector<vector<int>> sum(1 << id, vector<int>(lim));
    for (int bit = 0; bit < (1 << id); bit++) {
      for (int i = 0; i < id; i++) {
        if (bit >> i & 1) {
          int orig_id = inv[i];
          for (int t = 0; t < lim; t++) {
            sum[bit][t] += disc[orig_id][t];
          }
        }
      }
    }

    priority_queue<Elem> que;
    que.push(Elem{sx, sy, 0, 0, 0});
    rec[sx][sy][0][0] = 0;

    while (que.size()) {
      Elem cur = que.top();
      que.pop();
      int x = cur.x, y = cur.y, bit = cur.bit, time = cur.time, cost = cur.cost;
      chmax(ans, cost);
      if (cost < rec[x][y][time][bit] || time >= lim)
        continue;

      // 商品を取る
      int cand = 0;
      for (int k = 0; k < 4; k++) {
        int mx = x + dx[k], my = y + dy[k];
        if (!(mx < 0 || mx >= H || my < 0 || my >= W) and
            ('0' <= board[mx][my] && board[mx][my] <= '9')) {
          int c = comp[board[mx][my] - '0']; // 圧縮する
          if (bit >> c & 1)
            continue;
          cand |= (1 << c);
        }
      }

      for (int mask = cand; mask >= 0; mask = (mask - 1) & cand) {
        int nbit = bit | mask;
        int ncost = cost + sum[mask][time];

        // 移動先
        for (int k = 0; k < 4; k++) {
          int nx = x + dx[k], ny = y + dy[k], ntime = time + 1;
          if (!(nx < 0 || nx >= H || ny < 0 || ny >= W) and
              !('0' <= board[nx][ny] && board[nx][ny] <= '9') and
              (rec[nx][ny][ntime][nbit] < ncost)) {
            rec[nx][ny][ntime][nbit] = ncost;
            que.push(Elem{nx, ny, ntime, nbit, ncost});
          }
        }

        if (mask == 0)
          break;
      }
    }
    cout << ans << endl;
  }
  return 0;
}


Error: TLE

Fixed submission:

// 基本テンプレート

#include <algorithm>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

#define rep(i, a, n) for (int(i) = (a); (i) < (n); (i)++)
#define repq(i, a, n) for (int(i) = (a); (i) <= (n); (i)++)
#define repr(i, a, n) for (int(i) = (a); (i) >= (n); (i)--)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define int long long int

template <typename T> void chmax(T &a, T b) { a = max(a, b); }
template <typename T> void chmin(T &a, T b) { a = min(a, b); }
template <typename T> void chadd(T &a, T b) { a = a + b; }

typedef pair<int, int> pii;
typedef long long ll;

int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const ll INF = 1001001001001001LL;
const ll MOD = 1000000007LL;

char board[30][30];
int H, W, disc[10][105], rec[20][20][105][1 << 8];

struct Elem {
  int x, y, time, bit, cost;
  bool operator<(const Elem &e) const { return cost < e.cost; }
};

signed main() {
  while (cin >> W >> H, H || W) {
    memset(disc, 0, sizeof(disc));
    memset(rec, -1, sizeof(rec));
    int sx = -1, sy = -1;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        cin >> board[i][j];
        if (board[i][j] == 'P')
          sx = i, sy = j;
      }
    }

    int N, lim = 0, ans = 0;
    cin >> N;
    map<int, int> comp;
    for (int i = 0; i < N; i++) {
      int g, d, s, e;
      cin >> g >> d >> s >> e;
      comp[g]++;
      chmax(lim, e + 1);
      for (int k = s; k < e; k++) {
        chmax(disc[g][k], d);
      }
    }

    // ざあつ
    int id = 0;
    for (auto &x : comp) {
      x.second = id++;
    }
    vector<int> inv(id);
    for (auto x : comp) {
      inv[x.second] = x.first;
    }

    // cand の部分集合
    vector<vector<int>> sum(1 << id, vector<int>(lim));
    for (int bit = 0; bit < (1 << id); bit++) {
      for (int i = 0; i < id; i++) {
        if (bit >> i & 1) {
          int orig_id = inv[i];
          for (int t = 0; t < lim; t++) {
            sum[bit][t] += disc[orig_id][t];
          }
        }
      }
    }

    priority_queue<Elem> que;
    que.push(Elem{sx, sy, 0, 0, 0});
    rec[sx][sy][0][0] = 0;

    while (que.size()) {
      Elem cur = que.top();
      que.pop();
      int x = cur.x, y = cur.y, bit = cur.bit, time = cur.time, cost = cur.cost;
      chmax(ans, cost);
      if (cost < rec[x][y][time][bit] || time >= lim)
        continue;

      // 商品を取る
      int cand = 0;
      for (int k = 0; k < 4; k++) {
        int mx = x + dx[k], my = y + dy[k];
        if (!(mx < 0 || mx >= H || my < 0 || my >= W) and
            ('0' <= board[mx][my] && board[mx][my] <= '9')) {
          int c = comp[board[mx][my] - '0']; // 圧縮する
          if (bit >> c & 1)
            continue;
          cand |= (1 << c);
        }
      }

      for (int mask = cand; mask >= 0; mask = (mask - 1) & cand) {
        int nbit = bit | mask;
        int ncost = cost + sum[mask][time];

        // 移動先
        for (int k = 0; k < 4; k++) {
          int nx = x + dx[k], ny = y + dy[k], ntime = time + 1;
          if (!(nx < 0 || nx >= H || ny < 0 || ny >= W) and
              !('0' <= board[nx][ny] && board[nx][ny] <= '9') and
              (rec[nx][ny][ntime][nbit] < ncost)) {
            rec[nx][ny][ntime][nbit] = ncost;
            que.push(Elem{nx, ny, ntime, nbit, ncost});
          }
        }

        if (mask == 0)
          break;
      }
    }
    cout << ans << endl;
  }
  return 0;
}