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

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;

class Situation {
public:
  int oxigen;
  int money;
  int h, w;
  int miningCnt;
  // ¡¢ésÌóÔ
  int bitmask;
  // êxKê½ÀWXg
  set<pair<int, int>> visited;
};
// mem[h][w][k](h,w)É_fkÅB·é½ßÉKvÈÅ¬ïp
// OÌÀWÆA@Á½ñàJEgµÄ¨­
int mem[11][11][1 << 10][51];
int field[11][11];
const int INF = 100000000;
const int dy[] = {0, 0, 1};
const int dx[] = {-1, 1, 0};

void solve() {
  int h, w;
  int f, m, o;
  while (cin >> w >> h && !(w == 0 && h == 0)) {
    queue<Situation> q;
    for (int i = 0; i < 11; i++)
      for (int j = 0; j < 11; j++)
        for (int k = 0; k < (1 << 10); k++)
          fill(mem[i][j][k], mem[i][j][k] + 51, INF);
    cin >> f >> m >> o;
    // fieldîñ
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        cin >> field[i][j];
        field[i][j] = -field[i][j];
      }
    }
    for (int i = 0; i < w; i++) {
      Situation s;
      s.money = 0;
      s.miningCnt = 1;
      s.oxigen = o;
      s.h = 0;
      s.w = i;
      s.bitmask = (1 << i);
      s.visited.insert(make_pair(s.h, s.w));
      s.oxigen--;
      if (s.oxigen >= 1) {
        if (field[s.h][s.w] > 0)
          s.money += field[s.h][s.w];
        // _fÅ éê
        else
          s.oxigen = min(m, s.oxigen - field[s.h][s.w]);
        // ­@ïpªÜ¾cÁÄ¢éê
        if (s.money <= f && s.oxigen >= 1) {
          mem[s.h][s.w][(1 << i)][s.oxigen] = s.money;
          q.push(s);
        }
      }
    }
    int minGoalCost = INF;
    while (q.size()) {
      Situation s = q.front();
      q.pop();
      if (s.h == h - 1 || s.oxigen <= 1) {
        if (s.h == h - 1 && s.oxigen >= 1)
          minGoalCost = min(minGoalCost, s.money);
        continue;
      }
      // eûüÖÚ®
      for (int i = 0; i < 3; i++) {
        int toH = s.h + dy[i];
        int toW = s.w + dx[i];
        int toCost = s.money;
        int toOx = s.oxigen - 1;
        int toMining = s.miningCnt;
        if (toH >= 0 && toW >= 0 && toH < h && toW < w) {
          if (s.visited.find(make_pair(toH, toW)) == s.visited.end()) {
            if (field[toH][toW] > 0)
              toCost += field[toH][toW];
            // _fÅ éê
            else
              toOx = min(m, toOx - field[toH][toW]);
            toMining++;
          }
          Situation ns;
          ns.h = toH;
          ns.w = toW;
          ns.money = toCost;
          ns.visited = s.visited;
          ns.oxigen = toOx;
          ns.visited.insert(make_pair(toH, toW));
          ns.miningCnt = toMining;
          ns.bitmask = s.bitmask;
          if (i == 2)
            ns.bitmask = (1 << ns.w);
          else
            ns.bitmask |= (1 << ns.w);
          // ¡ñKêéêÌàÆàÆÌRXgæè¬³¢ê
          if (mem[toH][toW][ns.bitmask][toOx] > toCost && toCost <= f &&
              toCost <= minGoalCost) {
            if (toH != h - 1)
              q.push(ns);
            else
              minGoalCost = min(minGoalCost, ns.money);
            mem[toH][toW][ns.bitmask][toOx] =
                min(mem[toH][toW][ns.bitmask][toOx], toCost);
          }
        }
      }
    }
    if (minGoalCost == INF)
      cout << "NA" << endl;
    else
      cout << minGoalCost << endl;
  }
}

int main() {
  solve();
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;

class Situation {
public:
  int oxigen;
  int money;
  int h, w;
  int miningCnt;
  // êxKê½ÀWXg
  set<pair<int, int>> visited;
};

// mem[h][w][k](h,w)É_fkÅB·é½ßÉKvÈÅ¬ïp
// OÌÀWÆA@Á½ñàJEgµÄ¨­
int mem[11][11][4][101][51];
int field[11][11];
const int INF = 100000000;

const int dy[] = {0, 0, 1};
const int dx[] = {-1, 1, 0};

//  éê©ç éêÖÚ®·éÌÉKvÈÅ¬ïp
int minMiningCost[11][11];

int main() {
  int h, w;
  int f, m, o;
  while (cin >> w >> h && !(w == 0 && h == 0)) {
    queue<Situation> q;
    for (int i = 0; i < 11; i++)
      for (int j = 0; j < 11; j++)
        for (int k = 0; k < 4; k++)
          for (int l = 0; l < 101; l++)
            fill(mem[i][j][k][l], mem[i][j][k][l] + 51, INF);
    cin >> f >> m >> o;
    // fieldîñ
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        cin >> field[i][j];
        field[i][j] = -field[i][j];
        minMiningCost[i][j] = INF;
      }
    }

    int tmp[11][11];
    memset(tmp, 0, sizeof(tmp));
    bool ff = false;
    //  éÓ©çºÖü©¤ÌÉKvÈÅ¬RXg(©ÏàèÍKj
    for (int i = h - 1; i >= 0; i--) {
      int minC = INF;
      for (int j = 0; j < w; j++) {
        if (i == h - 1) {
          minMiningCost[i][j] = 0;
        } else {
          if (field[i + 1][j] > 0)
            tmp[i][j] = tmp[i + 1][j] + field[i + 1][j];
          else
            tmp[i][j] = tmp[i + 1][j];
          minC = min(minC, tmp[i][j]);
        }
      }
      if (i == h - 1)
        continue;
      for (int j = 0; j < w; j++) {
        minMiningCost[i][j] = minC;
      }
      if (i == 0) {
        if (minC > f) {
          ff = true;
        }
      }
    }
    if (ff) {
      cout << "NA" << endl;
      continue;
    }

    // for(int i = 0; i < w; i++){
    //     if(field[0][i]<0)
    //         minMiningCost[0][i]=field[0][i];
    // }

    // for(int i = 0; i < h; i++){
    //     for(int j = 0; j < w; j++){
    //         // 3ûü©çJÚ
    //         for(int k = 0; k < 3; k++){
    //             int ny=i+dy[k];
    //             int nx=j+dx[k];
    //             if(ny>=0&&nx>=0&&ny<h&&nx<w){
    //                 minMiningCost[i][j]=min(minMiningCost[i][j],minMiningCost[ny][nx]
    //             }
    //         }
    //     }
    // }

    for (int i = 0; i < w; i++) {
      Situation s;
      s.money = 0;
      s.miningCnt = 1;
      s.oxigen = o;
      s.h = 0;
      s.w = i;
      s.visited.insert(make_pair(s.h, s.w));
      s.oxigen--;
      if (field[s.h][s.w] > 0)
        s.money += field[s.h][s.w];
      // _fÅ éê
      else
        s.oxigen = min(m, s.oxigen - field[s.h][s.w]);
      // ­@ïpªÜ¾cÁÄ¢éê
      if (s.money <= f && s.oxigen >= 1) {
        mem[s.h][s.w][2][s.miningCnt][s.oxigen] = s.money;
        q.push(s);
      }
    }
    int minGoalCost = INF;
    int minCost = INF;
    while (q.size()) {
      Situation s = q.front();
      q.pop();
      if (s.h == h - 1 || s.oxigen <= 1) {
        if (s.h == h - 1)
          minGoalCost = min(minGoalCost, s.money);
        continue;
      }
      // eûüÖÚ®
      for (int i = 0; i < 3; i++) {
        int toH = s.h + dy[i];
        int toW = s.w + dx[i];
        int toCost = s.money;
        int toOx = s.oxigen - 1;
        int toMining = s.miningCnt;
        if (toH >= 0 && toW >= 0 && toH < h && toW < w) {
          if (s.visited.find(make_pair(toH, toW)) == s.visited.end()) {
            if (field[toH][toW] > 0)
              toCost += field[toH][toW];
            // _fÅ éê
            else
              toOx = min(m, toOx - field[toH][toW]);
            toMining++;
          }
          Situation ns;
          ns.h = toH;
          ns.w = toW;
          ns.money = toCost;
          ns.visited = s.visited;
          ns.oxigen = toOx;
          ns.visited.insert(make_pair(toH, toW));
          ns.miningCnt = toMining;
          // ¡ñKêéêÌàÆàÆÌRXgæè¬³¢ê
          if (mem[toH][toW][i][s.miningCnt][toOx] > toCost && toCost <= f &&
              toCost <= minGoalCost && f - toCost >= minMiningCost[toH][toW]) {
            if (toH != h - 1)
              q.push(ns);
            else
              minGoalCost = min(minGoalCost, ns.money);
            mem[toH][toW][i][s.miningCnt][toOx] =
                min(mem[toH][toW][i][s.miningCnt][toOx], toCost);
          }
        }
      }
    }
    if (minGoalCost == INF)
      cout << "NA" << endl;
    else
      cout << minGoalCost << endl;
  }
  return 0;
}