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


#include <iostream>
#include <queue>
#include <vector>
#define INF 1000
using namespace std;

typedef pair<int, int> P;

int H, W;
int mindep;       // 最小手数
char MAP[12][12]; // 可変マップデータ( 外側番兵 )
char has[4] = "RGB";

// 領域の面積を戻り値とする
int BFS(char color) {
  queue<P> que;
  P now;
  char map11 = MAP[1][1];
  int i;
  int dx[4] = {0, 1, 0, -1};
  int dy[4] = {1, 0, -1, 0};
  int ret = 0;

  que.push(P(1, 1));
  while (!que.empty()) {
    now = que.front();
    que.pop();
    if (MAP[now.first][now.second] != map11)
      continue;
    ret++;
    MAP[now.first][now.second] = color;
    for (i = 0; i < 4; i++)
      que.push(P(now.first + dy[i], now.second + dx[i]));
  }
  return ret;
}

// depth=操作回数,maxcount1=最多の色ブロックの個数(操作前)
int draw(int depth, int maxcount1) {
  char color = MAP[1][1]; // 1行1列の色(文字)
  char map[12][12] = {0}; // 今のマップデータ
  // int cnt[3] = {0};				//R,G,Bブロックの数
  int maxcount2; // 今の最多の色ブロックの個数(操作前)
  int i, j;

  if (mindep <= depth)
    return INF;

  for (i = 1; i < H + 1; i++) {
    for (j = 1; j < W + 1; j++) {
      map[i][j] = MAP[i][j];
      /*if( MAP[i][j] == 'R' )
              cnt[0]++;
      if( MAP[i][j] == 'B' )
              cnt[1]++;
      if( MAP[i][j] == 'G' )
              cnt[2]++;*/
    }
  }
  // cout << cnt[0] << " " << cnt[1] << " " << cnt[2] << endl;

  int ret[3] = {1000, 1000, 1000}; // 戻り値

  for (i = 0; i < 3; i++) {
    if (has[i] == color)
      continue;
    // MAP[1][1]と同じ色の1つの領域をhas[i]色にする.
    maxcount2 = BFS(has[i]);
    if (maxcount2 == H * W)
      return depth;
    if (maxcount1 >= maxcount2) {
      continue;
    }
    ret[i] = draw(depth + 1, maxcount2);
    // MAPの内容をもとに戻す
    for (j = 1; j < H + 1; j++) {
      for (int k = 1; k < W + 1; k++) {
        MAP[j][k] = map[j][k];
      }
    }
  }
  mindep = min(mindep, min(ret[0], min(ret[1], ret[2])));
  return min(ret[0], min(ret[1], ret[2]));
}

int main() {
  int i, j, k;
  int cnt[3] = {0}; // R,B,Gブロックの数
  int ans[1000] = {0};

  for (i = 0; cin >> W >> H; i++) {
    if (W == 0 && H == 0)
      break;
    mindep = INF;
    for (j = 0; j < H + 2; j++) {
      for (k = 0; k < W + 2; k++) {
        MAP[j][k] = 0;
      }
    }

    for (j = 1; j < H + 1; j++) {
      for (k = 1; k < W + 1; k++) {
        cin >> MAP[j][k];
        if (MAP[j][k] == '\\n' || MAP[j][k] == '\\r') {
          k--;
          continue;
        }
      }
    }
    ans[i] = draw(0, 0);
    cout << ans[i] << endl;
  }

  /*for( j = 0;j < i;j++ ){
          cout << ans[j] << endl;
  }*/
  return 0;
}

Error: TLE

Fixed submission:


#include <iostream>
#include <queue>
#include <vector>
#define INF 1000
using namespace std;

typedef pair<int, int> P;

int H, W;
char MAP[12][12]; // 可変マップデータ( 外側番兵 )
char has[4] = "RGB";

// 領域の面積を戻り値とする
int BFS(char color) {
  queue<P> que;
  P now;
  char map11 = MAP[1][1];
  int i;
  int dx[4] = {0, 1, 0, -1};
  int dy[4] = {1, 0, -1, 0};
  int ret = 0;

  que.push(P(1, 1));
  while (!que.empty()) {
    now = que.front();
    que.pop();
    if (MAP[now.first][now.second] != map11)
      continue;
    ret++;
    MAP[now.first][now.second] = color;
    for (i = 0; i < 4; i++)
      que.push(P(now.first + dy[i], now.second + dx[i]));
  }
  return ret;
}

// depth=操作回数,maxcount1=最多の色ブロックの個数(操作前)
int draw(int depth, int maxcount1) {
  char color = MAP[1][1]; // 1行1列の色(文字)
  char map[12][12] = {0}; // 今のマップデータ
  // int cnt[3] = {0};				//R,G,Bブロックの数
  int maxcount2; // 今の最多の色ブロックの個数(操作前)
  int i, j;

  for (i = 1; i < H + 1; i++) {
    for (j = 1; j < W + 1; j++) {
      map[i][j] = MAP[i][j];
      /*if( MAP[i][j] == 'R' )
              cnt[0]++;
      if( MAP[i][j] == 'B' )
              cnt[1]++;
      if( MAP[i][j] == 'G' )
              cnt[2]++;*/
    }
  }
  // cout << cnt[0] << " " << cnt[1] << " " << cnt[2] << endl;

  int ret[3] = {1000, 1000, 1000}; // 戻り値

  for (i = 0; i < 3; i++) {
    if (has[i] == color)
      continue;
    // MAP[1][1]と同じ色の1つの領域をhas[i]色にする.
    maxcount2 = BFS(has[i]);
    if (maxcount2 == H * W)
      return depth;
    if (maxcount1 >= maxcount2) {
      continue;
    }
    ret[i] = draw(depth + 1, maxcount2);
    // MAPの内容をもとに戻す
    for (j = 1; j < H + 1; j++) {
      for (int k = 1; k < W + 1; k++) {
        MAP[j][k] = map[j][k];
      }
    }
  }
  return min(ret[0], min(ret[1], ret[2]));
}

int main() {
  int i, j, k;
  int cnt[3] = {0}; // R,B,Gブロックの数
  int ans[1000] = {0};

  for (i = 0; cin >> W >> H; i++) {
    if (W == 0 && H == 0)
      break;
    for (j = 0; j < H + 2; j++) {
      for (k = 0; k < W + 2; k++) {
        MAP[j][k] = 0;
      }
    }

    for (j = 1; j < H + 1; j++) {
      for (k = 1; k < W + 1; k++) {
        cin >> MAP[j][k];
        if (MAP[j][k] == '\\n' || MAP[j][k] == '\\r') {
          k--;
          continue;
        }
      }
    }
    ans[i] = draw(0, 0);
    cout << ans[i] << endl;
  }

  /*for( j = 0;j < i;j++ ){
          cout << ans[j] << endl;
  }*/
  return 0;
}