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

#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

int main() {
  int init_hp, max_hp;
  while (cin >> init_hp >> max_hp, init_hp | max_hp) {
    int r, c;
    cin >> r >> c;
    vs a(r);
    REP(i, r) { cin >> a[i]; }

    int t;
    cin >> t;
    map<char, int> d;
    REP(i, t) {
      char c;
      int dd;
      cin >> c >> dd;
      d[c] = dd;
    }
    int s;
    cin >> s;
    int cy = 0, cx = 0;
    vi damages;
    REP(i, s) {
      char dd;
      int n;
      cin >> dd >> n;
      int dy = 0, dx = 0;
      switch (dd) {
      case 'U':
        dy = -1;
        break;
      case 'D':
        dy = 1;
        break;
      case 'L':
        dx = -1;
        break;
      case 'R':
        dx = 1;
        break;
      }
      REP(j, n) {
        cy += dy;
        cx += dx;
        damages.push_back(d[a[cy][cx]]);
      }
    }

    int P;
    cin >> P;
    vi p(P);
    REP(i, P) { cin >> p[i]; }

    vi cured(1 << P);
    REP(i, 1 << P) {
      REP(j, P) {
        if ((i >> j) & 1) {
          cured[i] += p[j];
        }
      }
    }

    int n = damages.size();
    vvi dp(n + 1, vi(1 << P));
    dp[0][0] = init_hp;
    REP(i, n) {
      REP(j, 1 << P) {
        if (dp[i][j] > 0) {
          if (dp[i][j] <= damages[i]) {
            REP(k, 1 << P) {
              bool ok = true;
              if (j & k) {
                ok = false;
              }
              if (ok) {
                dp[i + 1][j | k] =
                    max(dp[i + 1][j | k],
                        min(max_hp, dp[i][j] + cured[k]) - damages[i]);
              }
            }
          } else {
            dp[i + 1][j] = max(dp[i + 1][j], dp[i][j] - damages[i]);
          }
        }
      }
    }
    /*
    REP(i,n+1){
      REP(j,1<<P){
        cerr<<i<<" "<<j<<" "<<dp[i][j]<<endl;
      }
    }
    */
    bool ok = false;
    REP(j, 1 << P) {
      if (dp[n][j] > 0) {
        ok = true;
      }
    }
    cout << (ok ? "YES" : "NO") << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

int main() {
  int init_hp, max_hp;
  while (cin >> init_hp >> max_hp, init_hp | max_hp) {
    int r, c;
    cin >> r >> c;
    vs a(r);
    REP(i, r) { cin >> a[i]; }

    int t;
    cin >> t;
    map<char, int> d;
    REP(i, t) {
      char c;
      int dd;
      cin >> c >> dd;
      d[c] = dd;
    }
    int s;
    cin >> s;
    int cy = 0, cx = 0;
    vi damages(1);
    REP(i, s) {
      char dd;
      int n;
      cin >> dd >> n;
      int dy = 0, dx = 0;
      switch (dd) {
      case 'U':
        dy = -1;
        break;
      case 'D':
        dy = 1;
        break;
      case 'L':
        dx = -1;
        break;
      case 'R':
        dx = 1;
        break;
      }
      REP(j, n) {
        cy += dy;
        cx += dx;
        damages.push_back(d[a[cy][cx]]);
      }
    }

    int P;
    cin >> P;
    vi p(P);
    REP(i, P) { cin >> p[i]; }

    int n = damages.size();
    vvi dp(n + 1, vi(1 << P));
    dp[0][0] = init_hp;
    REP(i, n) {
      REP(j, 1 << P) {
        if (dp[i][j] > 0) {
          if (dp[i][j] <= damages[i]) {
            REP(k, 1 << P) {
              bool ok = true;
              int cured = 0;
              REP(l, P) {
                if ((k >> l) & 1) {
                  cured += p[l];
                }
                if ((j >> l) & (k >> l) & 1) {
                  ok = false;
                }
              }
              if (ok) {
                dp[i + 1][j | k] =
                    max(dp[i + 1][j | k],
                        min(max_hp, dp[i][j] + cured - damages[i]));
              }
            }
          } else {
            dp[i + 1][j] = max(dp[i + 1][j], dp[i][j] - damages[i]);
          }
        }
      }
    }
    /*
    REP(i,n+1){
      REP(j,1<<P){
        cerr<<i<<" "<<j<<" "<<dp[i][j]<<endl;
      }
    }
    */
    bool ok = false;
    REP(j, 1 << P) {
      if (dp[n][j] > 0) {
        ok = true;
      }
    }
    cout << (ok ? "YES" : "NO") << endl;
  }
}