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

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>

#define M 100
#define N 100
#define SINGLE 1
#define ALL 2
#define INFTY 1 << 28
#define MAX_HP 100001

using namespace std;

struct monster {
  int hp;
};

struct magic {
  int mp;
  int type;
  int damage;
};

void min_mp(int *min, int max_hp, const vector<magic> &vmag) {
  int m = vmag.size();

  for (int i = 0; i < max_hp; ++i) {
    min[i] = INFTY;
  }

  if (m == 0)
    return;

  int **dp = new int *[m];
  for (int i = 0; i < m; ++i) {
    dp[i] = new int[max_hp];
  }

  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < max_hp; ++j) {
      dp[i][j] = INFTY;
    }
  }

  dp[0][0] = 0;
  for (int i = 0; i < m; ++i) {
    int mp = vmag[i].mp;
    int damage = vmag[i].damage;

    for (int j = 0; j < max_hp; ++j) {
      if (dp[i][j] < INFTY) {
        if (i + 1 < m)
          dp[i + 1][j] = std::min(dp[i + 1][j], dp[i][j]);
        int &t = dp[i][std::min(j + damage, max_hp - 1)];
        t = std::min(t, dp[i][j] + mp);
      }
    }
  }

  min[max_hp - 1] = dp[m - 1][max_hp - 1];
  for (int i = max_hp - 2; i >= 0; --i) {
    min[i] = std::min(min[i + 1], dp[m - 1][i]);
  }

  for (int i = 0; i < m; ++i) {
    delete[] dp[i];
  }
  delete[] dp;
}
int MagicSlayer(const vector<monster> &vmon, const vector<magic> &vmag) {
  int ret = INFTY;
  vector<magic> vmag_single;
  vector<magic> vmag_all;
  int max_hp = 0;
  int min_mp_single[MAX_HP] = {
      0,
  };
  int min_mp_all[MAX_HP] = {
      0,
  };

  for (unsigned int i = 0; i < vmon.size(); ++i) {
    max_hp = max(max_hp, vmon[i].hp);
  }
  ++max_hp;

  for (unsigned int i = 0; i < vmag.size(); ++i) {
    if (vmag[i].type == ALL)
      vmag_all.push_back(vmag[i]);
    else
      vmag_single.push_back(vmag[i]);
  }

  min_mp(min_mp_single, max_hp, vmag_single);
  min_mp(min_mp_all, max_hp, vmag_all);

  /*for(int i = 0; i < max_hp; ++i){
          if( i % 500 == 0 )
                  cout << "DAMAGE: " << i << " MP: " << min_mp_single[i] <<
  endl;
  }*/

  for (int i = 0; i < max_hp; ++i) {
    int dam;
    int mp;

    if (min_mp_all[i] >= INFTY) {
      dam = 0;
      mp = 0;
    } else {
      dam = i;
      mp = min_mp_all[i];
    }

    for (unsigned int j = 0; j < vmon.size(); ++j) {
      if (vmon[j].hp - dam > 0) {
        int t = min_mp_single[vmon[j].hp - dam];
        if (t >= INFTY) {
          mp = INFTY;
          break;
        } else {
          mp += t;
        }
      }
    }

    ret = min(ret, mp);
  }

  return ret;
}

int main() {
  while (true) {
    int n, m;
    vector<monster> vmonster;
    vector<magic> vmagic;

    scanf("%d", &n);
    if (n == 0)
      break;
    for (int i = 0; i < n; ++i) {
      monster t;

      scanf("%d", &t.hp);
      vmonster.push_back(t);
    }

    scanf("%d", &m);
    for (int i = 0; i < m; ++i) {
      char stype[17] = "";
      magic mag;

      scanf("%*s%d%s%d", &mag.mp, stype, &mag.damage);
      if (strcmp(stype, "All") == 0)
        mag.type = ALL;
      else
        mag.type = SINGLE;
      vmagic.push_back(mag);
    }

    printf("%d\\n", MagicSlayer(vmonster, vmagic));
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>

#define M 100
#define N 100
#define SINGLE 1
#define ALL 2
#define INFTY 1 << 30

using namespace std;

struct magic {
  int mp;
  int type;
  int damage;
  bool operator<(const magic &m) const { return mp < m.mp; }
};

struct state {
  state() : sum_mp(0), rest(0) {}
  vector<int> vhp;
  int sum_mp;
  int rest;
  bool bComp() const {
    if (rest <= 0)
      return true;
    else
      return false;
  }
  bool operator<(const state &t) const { return sum_mp < t.sum_mp; }
  int getHeuristic(double best_rate) const {
    return (int)(rest / best_rate + 0.5);
  }
};

ostream &operator<<(ostream &os, const state &t) {
  os << "HP: ";
  for (unsigned int i = 0; i < t.vhp.size(); ++i) {
    os << t.vhp[i] << ' ';
  }
  os << "\\nSUM MP: " << t.sum_mp << " REST HP: " << t.rest;
  return os;
}
void dfs(const state &now, const vector<magic> &vmag, double best_rate,
         int limit, int &best_ans) {
  int n = now.vhp.size();

  // cout<<now<<endl;

  if (now.sum_mp + now.getHeuristic(best_rate) >= best_ans)
    return;

  if (now.bComp()) {
    best_ans = min(best_ans, now.sum_mp);
    return;
  }

  for (unsigned int i = 0; i < vmag.size(); ++i) {
    if (now.sum_mp + vmag[i].mp >= best_ans && now.sum_mp + vmag[i].mp < limit)
      continue;

    if (vmag[i].type == ALL) {
      state t = now;
      for (int j = 0; j < n; ++j) {
        if (t.vhp[j] > 0) {
          t.rest -= min(t.vhp[j], vmag[i].damage);
          t.vhp[j] -= vmag[i].damage;
        }
      }
      t.sum_mp += vmag[i].mp;
      if (t.sum_mp + t.getHeuristic(best_rate) < best_ans)
        dfs(t, vmag, best_rate, limit, best_ans);
    } else {
      for (int j = 0; j < n; ++j) {
        if (now.vhp[j] > 0) {
          state t = now;
          t.rest -= min(t.vhp[j], vmag[i].damage);
          t.vhp[j] -= vmag[i].damage;
          t.sum_mp += vmag[i].mp;
          if (t.sum_mp + t.getHeuristic(best_rate) < best_ans)
            dfs(t, vmag, best_rate, limit, best_ans);
        }
      }
    }
  }

  return;
}
void solve(const state &ini, const vector<magic> &vmag, double best_rate,
           int &best_ans) {
  int n = ini.vhp.size();
  priority_queue<state> qs;

  qs.push(ini);

  while (!qs.empty()) {
    state st = qs.top();
    qs.pop();

    cout << st << endl;
    if (st.sum_mp + st.getHeuristic(best_rate) >= best_ans)
      break;

    if (st.bComp()) {
      best_ans = min(best_ans, st.sum_mp);
      continue;
    }

    for (unsigned int i = 0; i < vmag.size(); ++i) {
      if (st.sum_mp + vmag[i].mp >= best_ans)
        continue;
      if (vmag[i].type == ALL) {
        state t = st;
        for (int j = 0; j < n; ++j) {
          if (t.vhp[j] > 0) {
            t.rest -= min(t.vhp[j], vmag[i].damage);
            t.vhp[j] -= vmag[i].damage;
          }
        }
        t.sum_mp += vmag[i].mp;
        if (t.sum_mp + t.getHeuristic(best_rate) < best_ans)
          qs.push(t);
      } else {
        for (int j = 0; j < n; ++j) {
          if (st.vhp[j] > 0) {
            state t = st;
            t.rest -= min(t.vhp[j], vmag[i].damage);
            t.vhp[j] -= vmag[i].damage;
            t.sum_mp += vmag[i].mp;
            if (t.sum_mp + t.getHeuristic(best_rate) < best_ans)
              qs.push(t);
            break;
          }
        }
      }
    }
  }
  return;
}

int main() {
  while (true) {
    int n, m;
    int ans = INFTY;
    double best_rate = 0.0;
    vector<magic> vmagic;
    magic magic_for_greedy;
    state init;

    scanf("%d", &n);
    if (n == 0)
      break;
    for (int i = 0; i < n; ++i) {
      int t;
      scanf("%d", &t);
      init.rest += t;
      init.vhp.push_back(t);
    }
    scanf("%d", &m);
    for (int i = 0; i < m; ++i) {
      int mp, type, damage;
      char stype[17] = "";

      scanf("%*s%d%s%d", &mp, stype, &damage);

      if (strcmp(stype, "All") == 0)
        type = ALL;
      else
        type = SINGLE;

      if (damage > 0 && mp == 0) {
        best_rate = -2.0;
        break;
      }

      if (damage > 0 && mp > 0) {
        magic tm;
        if (best_rate < (double)damage * (type == ALL ? n : 1) / mp) {
          best_rate = (double)damage * (type == ALL ? n : 1) / mp;
          magic_for_greedy.damage = damage;
          magic_for_greedy.mp = mp;
          magic_for_greedy.type = type;
        }
        tm.damage = damage;
        tm.mp = mp;
        tm.type = type;
        vmagic.push_back(tm);
      }
    }

    if (magic_for_greedy.type == ALL) {
      int hp_max = 0;
      for (unsigned int i = 0; i < init.vhp.size(); ++i) {
        hp_max = max(hp_max, init.vhp[i]);
      }
      ans = magic_for_greedy.mp * ((hp_max % magic_for_greedy.damage ? 1 : 0) +
                                   hp_max / magic_for_greedy.damage);
    } else {
      ans = 0;
      for (unsigned int i = 0; i < init.vhp.size(); ++i) {
        ans += magic_for_greedy.mp *
               ((init.vhp[i] % magic_for_greedy.damage ? 1 : 0) +
                init.vhp[i] / magic_for_greedy.damage);
      }
    }

    if (best_rate < 0) {
      printf("0\\n");
      continue;
    }

    ans = INFTY;
    for (int i = 0; i < INFTY; i += 1000) {
      dfs(init, vmagic, best_rate, i, ans);
      if (ans < INFTY)
        break;
    }
    printf("%d\\n", ans);
  }
  return 0;
}