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

#include <cctype>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;

#define ME '@'
#define EXIT '<'
#define WALL '#'
#define EMPTY '.'

struct Data {
  int x, y, on;
};
bool operator<(Data a, Data b) {
  return a.x != b.x ? a.x < b.x : (a.y != b.y ? a.y < b.y : a.on < b.on);
}

int main() {
  int W, H;
  int i;
  int dx[4] = {1, 0, -1, 0};
  int dy[4] = {0, 1, 0, -1};
  int ans;
  while (cin >> W >> H, W | H) {
    vector<string> v(H);
    queue<Data> q;
    set<Data> visited;
    map<Data, int> cost;
    for (i = 0; i < H; i++) {
      cin >> v[i];
      if (v[i].find("@") != string::npos) {
        Data d;
        d.x = v[i].find("@");
        d.y = i;
        d.on = 0;
        q.push(d);
        v[d.y][d.x] = EMPTY;
      }
    }

    ans = -1;
    while (q.size()) {
      Data d = q.front();
      q.pop();
      if (ans != -1)
        break;
      if (visited.count(d))
        continue;
      visited.insert(d);
      for (i = 0; i < 4; i++) {
        Data dd = d;
        dd.x += dx[i];
        dd.y += dy[i];
        if (dd.x < 0 || W <= dd.x || dd.y < 0 || H <= dd.y)
          continue;
        if (v[dd.y][dd.x] == EXIT) {
          ans = cost[d] + 1;
          break;
        } else if (v[dd.y][dd.x] == WALL) {
          continue;
        } else if (v[dd.y][dd.x] == EMPTY) {
          q.push(dd);
          cost[dd] = cost[d] + 1;
        } else if (isupper(v[dd.y][dd.x])) {
          if (dd.on & (1 << (v[dd.y][dd.x] - 'A'))) {
            q.push(dd);
            cost[dd] = cost[d] + 1;
          }
        } else if (islower(v[dd.y][dd.x])) {
          dd.on ^= 1 << (v[dd.y][dd.x] - 'a');
          q.push(dd);
          cost[dd] = cost[d] + 1;
        }
      }
    }
    cout << ans << endl;
  }
}

Error: TLE

Fixed submission:

#include <cctype>
#include <iostream>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;

#define ME '@'
#define EXIT '<'
#define WALL '#'
#define EMPTY '.'

struct Data {
  int x, y, d;
  set<char> on;
};
struct Visit {
  int x, y;
  set<char> on;
};
bool operator<(Visit a, Visit b) {
  return (a.x != b.x ? a.x < b.x : (a.y != b.y ? a.y < b.y : a.on < b.on));
}

int main() {
  int W, H;
  int i;
  int dx[4] = {1, 0, -1, 0};
  int dy[4] = {0, 1, 0, -1};
  int ans;
  while (cin >> W >> H, W | H) {
    vector<string> v(H);
    queue<Data> q;
    set<Visit> visited;
    for (i = 0; i < H; i++) {
      cin >> v[i];
      if (v[i].find("@") != string::npos) {
        Data d;
        d.x = v[i].find("@");
        d.y = i;
        d.d = 0;
        q.push(d);
        v[d.y][d.x] = EMPTY;
      }
    }

    ans = -1;
    while (q.size()) {
      Data d = q.front();
      q.pop();
      if (ans != -1)
        break;
      if (d.d >= 100)
        break;
      Visit vv;
      vv.x = d.x;
      vv.y = d.y;
      vv.on = d.on;
      if (visited.count(vv))
        continue;
      visited.insert(vv);
      for (i = 0; i < 4; i++) {
        Data dd = d;
        dd.x += dx[i];
        dd.y += dy[i];
        dd.d++;
        if (dd.x < 0 || W <= dd.x || dd.y < 0 || H <= dd.y)
          continue;
        if (v[dd.y][dd.x] == EXIT) {
          ans = dd.d;
          break;
        } else if (v[dd.y][dd.x] == WALL) {
          continue;
        } else if (v[dd.y][dd.x] == EMPTY) {
          q.push(dd);
        } else if (isupper(v[dd.y][dd.x])) {
          if (dd.on.count(v[dd.y][dd.x] - 'A' + 'a'))
            q.push(dd);
        } else if (islower(v[dd.y][dd.x])) {
          if (dd.on.count(v[dd.y][dd.x])) {
            dd.on.erase(v[dd.y][dd.x]);
          } else {
            dd.on.insert(v[dd.y][dd.x]);
          }
          q.push(dd);
        }
      }
    }
    cout << ans << endl;
  }
}