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

#include <algorithm>
#include <iostream>
using namespace std;

int dx[] = {0, 1, 0, -1}; // 上下左右進む方向
int dy[] = {-1, 0, 1, 0};

// void dfs(int x, int y, int field[100][100]){
// 	if(field[x][y] == 0) return;	//行けなかったら終わり

// 	field[x][y] = 0;
// 	for(int k = 0; k < 4; k++){
// 		dfs(x + dx[k], y + dy[k], field);
// 	}
// }

// 深さ優先探索
int dfs(int x, int y,
        int field[100][100]) { // 引数は座標と今まで通ってきたフィールド
  int d = field[x][y];          // 今の場所の距離
  for (int k = 0; k < 4; k++) { // 上下左右進む
    int nextX = x + dx[k];      // 次に進む方向
    int nextY = y + dy[k];
    if (field[nextX][nextY] == 1) {          // もし次に進めたら
      field[nextX][nextY] = field[x][y] + 1; // 行った印,スタートからの距離
      d = max(d, dfs(nextX, nextY, field)); // 今の距離(今まで行った距離)と比較
      field[nextX][nextY] = 1; // もとに戻しておく
    }
  }

  return d; // その位置から行けるスタートからの最大距離を返す
}

int main() {
  int m, n;
  while (cin >> m >> n, m != 0 && n != 0) {
    /*入力*/
    int ice[100][100] = {{0}}; // 与えられる配列(外壁あり)
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= m; j++) {
        cin >> ice[i][j];
      }
    }

    /*計算*/
    int ans = 0;
    for (int i = 1; i <= m; i++) { // 始めの位置
      for (int j = 1; j <= n; j++) {
        if (ice[i][j] == 1) { // 氷があったら
          ice[i][j] = 2; // 行った印,スタートからの距離(0,1が使われているから2)
          ans = max(
              ans,
              dfs(i, j,
                  ice)); // 調べ終わった距離と、その位置からの行ける最大距離を比べる
          ice[i][j] = 1; // 氷を戻しておく
        }
      }
    }

    /*出力*/
    cout << ans - 1 << endl; // 2から始まっていたので-1する
  }
}

Error: TLE

Fixed submission:

/**********************
aoj_0535
Crossing Black Ice
***********************/
#include <cstring>
#include <iostream>
#include <stack>
using namespace std;

struct pos {
  int x; // 座標
  int y;
  int count;                // 進んだ数
  int after_move[100][100]; // 今まで進んだ配列を記憶する
};

int main() {
  while (1) {
    int m, n;
    cin >> m >> n;
    if (m == 0 || n == 0)
      break;

    /*入力*/
    int ice[100][100] = {{0}}; // 与えられる配列(外壁あり)
    //		for(int i = 0; i < 100; i++){		//配列の初期か
    //			for(int j = 0; j < 100; j++){
    //				ice[i][j] = 0;
    //			}
    //		}
    for (int i = 1; i <= n; i++) { // 配列をもらう
      for (int j = 1; j <= m; j++) {
        cin >> ice[i][j];
      }
    }

    /*最大移動数を数える(深さ優先探索)*/
    stack<pos> sta;                // スタック
    int ans = 0;                   // 回答する移動数の数
    for (int i = 1; i <= n; i++) { // 与えられた配列分まわす
      for (int j = 1; j <= m; j++) {
        /*深さ優先探索*/
        if (ice[i][j]) { // 氷だったらそこをスタート地点にする
          pos p; // スタックに入れるpを作りスタート地点の情報を入れていく
          p.x = j;
          p.y = i;
          p.count = 1;
          memcpy(p.after_move, ice, sizeof(p.after_move));
          p.after_move[i][j] = 0; // スタート地点の氷を割っておく
          sta.push(p);
          /*全パターン探す*/
          while (!sta.empty()) { // stackが空になったら終了
            int x1[] = {-1, 0, 1, 0}, y1[] = {0, 1, 0, -1}; // 移動先
            p = sta.top();           // スタックを取り出す
            sta.pop();               // スタックの先頭を削除
            ans = max(ans, p.count); // 進んだ数が最大なら記憶する
            for (int k = 0; k < 4; k++) { // 上下左右の４カ所分まわす
              pos p1 = p;                 // 移動
              p1.x += x1[k];
              p1.y += y1[k];                   // 移動先
              if (p1.after_move[p1.y][p1.x]) { // 異動先が氷なら
                p1.after_move[p1.y][p1.x] = 0; // 氷を割る
                p1.count++;                    // 進んだ数を増やす
                sta.push(p1);                  // スタックにいれる
              }
            }
          }
        }
      }
    }

    /*出力*/
    cout << ans << endl;
  }
  return 0;
}