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

#include <algorithm>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>

#define REP(i, n) for (int i = 0; i < n; i++)

using namespace std;

typedef vector<vector<int>> field;

int w, h;
field f, closed;
int mx[] = {0, 0, 1, -1}, my[] = {1, -1, 0, 0};

void dump(field &f, int x = -1, int y = -1) {
  REP(i, f.size()) {
    REP(j, f[i].size()) {
      if (y == i && x == j)
        cout << "# ";
      else
        cout << f[i][j] << " ";
    }
    cout << endl;
  }
}

int in_range(int x, int y, int w, int h) {
  return (int)(0 <= x && x < w && 0 <= y && y < h);
}

int bt(int x, int y, int step) {
  // printf("step:%d x:%d y:%d\\n", step, x, y);
  // dump(f, x, y);

  int res = INT_MAX, tmp;

  // 終了条件
  if (step == 10) {
    return res;
  }

  // 上下左右に進めるなら進む
  REP(i, 4) {
    int nx = x, ny = y;
    // cout << "-----" << endl;

    // int nx = x + mx[i],
    //     ny = y + my[i];

    // printf("x:%d y:%d f[ny][nx]:%d\\n", nx, ny, f[ny][nx]);

    // while(in_range(nx+mx[i], ny+my[i], w, h)) {
    while (1) {
      nx += mx[i];
      ny += my[i];

      if (!in_range(nx, ny, w, h)) {
        break;
      }
      // printf("nx:%d ny:%d f[ny][nx]:%d\\n", nx, ny, f[ny][nx]);

      if (f[ny][nx] == 1) {
        break;
      } else if (f[ny][nx] == 3) {
        return step + 1;
      }
    }

    if (!in_range(nx, ny, w, h) || abs(x - nx) == 1 || abs(y - ny) == 1)
      continue;
    // printf("nx:%d ny:%d inrange:%d\\n", nx, ny, in_range(nx, ny, w, h));
    // printf("push: %d, %d, %d mx[i]:%d, my[i]:%d\\n", (nx-mx[i]), (ny-my[i]),
    // (step+1), mx[i], my[i]); dump(f, nx, ny); cout << "hoge" << endl;

    // 障害物を破壊
    f[ny][nx] = 0;
    tmp = bt(nx - mx[i], ny - my[i], step + 1);
    f[ny][nx] = 1;

    // 最小手の更新
    if (tmp < res)
      res = tmp;
  }

  return res;
}

int main() {
  int fx, fy, res;

  while (cin >> w >> h, w || h) {
    f = field(h, vector<int>(w));
    // closed = field(h, vector<int>(w));

    // 入力
    REP(i, h) {
      REP(j, w) {
        cin >> f[i][j];
        if (f[i][j] == 2) {
          fx = j;
          fy = i;
        }
      }
    }
    // dump(f, fx, fy);

    res = bt(fx, fy, 0);

    if (res != INT_MAX)
      cout << res;
    else
      cout << -1;
    cout << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>

#define REP(i, n) for (int i = 0; i < n; i++)

using namespace std;

typedef vector<vector<int>> field;
typedef pair<int, int> crd;

int mx[] = {0, 0, 1, -1}, my[] = {1, -1, 0, 0};

void dump(field &f, int x = -1, int y = -1) {
  REP(i, f.size()) {
    REP(j, f[i].size()) {
      if (y == i && x == j)
        cout << "# ";
      else
        cout << f[i][j] << " ";
    }
    cout << endl;
  }
}

int in_range(int x, int y, int w, int h) {
  return (int)(0 <= x && x < w && 0 <= y && y < h);
}

field restore(field &f, vector<crd> &broken) {
  // cout << "broken: " << broken.size() << endl;
  REP(i, broken.size()) {
    // cout << broken[i].second << " " << broken[i].first << endl;
    f[broken[i].second][broken[i].first] = 0;
  }
  return f;
}

// x, y, マップの状態、ステップ数
int wfs(int w, int h, int x, int y, field f) {
  int step = 0;
  // vector<crd> b;
  queue<int> open;
  // queue<field> open_f;
  queue<vector<crd>> open_b;

  // 初期値をpush
  open.push(x);
  open.push(y);
  open.push(step);
  // open_f.push(f);

  vector<crd> b(0);
  open_b.push(b);

  while (!open.empty()) {
    int x = open.front();
    open.pop();
    int y = open.front();
    open.pop();
    int step = open.front();
    open.pop();

    vector<crd> b = open_b.front();
    open_b.pop();

    // field f = open_f.front(); open_f.pop();

    // 終了条件
    if (step > 10)
      return 0;
    if (f[y][x] == 3)
      return step;

    // printf("step:%d x:%d y:%d\\n", step, x, y);
    // dump(f, x, y);

    REP(i, 4) {
      int nx = x + mx[i], ny = y + my[i], flg = 0;

      vector<crd> tmp = b;
      // field tmp = f;

      // 破壊された障害物をリストア
      field fl = restore(f, b);
      // dump(fl);

      // 範囲外 or 障害物で進めないなら
      if (!in_range(nx, ny, w, h) || fl[ny][nx] == 1)
        continue;

      // ぶつかるまで直進
      while (in_range(nx, ny, w, h) && fl[ny][nx] != 1) {
        nx += mx[i];
        ny += my[i];
      }

      // printf("nx:%d ny:%d\\n", nx, ny);
      if (in_range(nx, ny, w, h)) {
        // 障害物を破壊
        tmp.push_back(make_pair(nx, ny));
      }
      // 行き過ぎてるので戻してpush
      open.push(nx - mx[i]);
      open.push(ny - my[i]);
      open.push(step + 1);

      // open_f.push(tmp);
      open_b.push(tmp);
    }
  }

  return 0;
}

int main() {
  int w, h;

  while (cin >> w >> h, w || h) {
    field f(h);
    f = field(h, vector<int>(w));

    // 入力
    REP(i, h) {
      REP(j, w) { cin >> f[i][j]; }
    }
    // dump(f);

    // スタート地点を見つけたら始める
    int res;
    REP(i, h) {
      REP(j, w) {
        if (f[i][j] == 2) {
          // res = wfs(w, h, j, i, 0, f);
          res = wfs(w, h, j, i, f);
        }
      }
    }

    if (res != 0)
      cout << res;
    else
      cout << -1;
    cout << endl;
  }

  return 0;
}