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

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

int W, H;
int field[20][20];
int field2[21][21];
int res;
const int dy[] = {-1, 0, 0, 1};
const int dx[] = {0, -1, 1, 0};
bool used[101][101];
int lim;

void fillField(int cy, int cx, int oldc, int newc, bool &ok, bool flag) {
  if (!flag)
    field[cy][cx] = newc;
  else
    field2[cy][cx] = newc;
  used[cy][cx] = true;
  for (int i = 0; i < 4; i++) {
    int ny = cy + dy[i];
    int nx = cx + dx[i];
    if (ny >= 0 && nx >= 0 && ny < H && nx < W && !used[ny][nx]) {
      if (!flag) {
        if (field[ny][nx] == oldc)
          fillField(ny, nx, oldc, newc, ok, flag);
        else if (field[ny][nx] == newc)
          ok = true;
      } else {
        if (field2[ny][nx] == oldc)
          fillField(ny, nx, oldc, newc, ok, flag);
        else if (field2[ny][nx] == newc)
          ok = true;
      }
    }
  }
}
void dfs(int cnt) {
  if (res <= cnt)
    return;
  {
    int goal = field[0][0];
    bool ok = true;
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++)
        if (field[i][j] != goal)
          ok = false;
    if (ok) {
      res = min(res, cnt);
      return;
    }
  }
  for (int i = 0; i < 3; i++) {
    if (field[0][0] == i)
      continue;
    int backUp[20][20];
    for (int j = 0; j < H; j++)
      for (int k = 0; k < W; k++)
        backUp[j][k] = field[j][k];
    bool ok = false;
    // 塗りつぶし
    memset(used, 0, sizeof(used));
    fillField(0, 0, field[0][0], i, ok, false);
    // もし一つ以上属する色が増えるならdfs
    if (ok)
      dfs(cnt + 1);
    for (int j = 0; j < H; j++)
      for (int k = 0; k < W; k++)
        field[j][k] = backUp[j][k];
  }
}
int greedy() {
  {
    int goal = field2[0][0];
    bool ok = true;
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++)
        if (field2[i][j] != goal)
          ok = false;
    if (ok)
      return 0;
  }
  for (int i = 0; i < 3; i++) {
    if (field2[0][0] == i)
      continue;
    bool ok = false;
    // 塗りつぶし
    fillField(0, 0, field2[0][0], i, ok, true);
    // もし一つ以上属する色が増えるならdfs
    if (ok)
      return greedy() + 1;
  }
}

int main() {
  while (cin >> W >> H && (W | H)) {
    res = H * W;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        char ch;
        cin >> ch;
        if (ch == 'R')
          field[i][j] = 0;
        else if (ch == 'G')
          field[i][j] = 1;
        else if (ch == 'B')
          field[i][j] = 2;
        field2[i][j] = field[i][j];
      }
    }
    lim = greedy();
    res = lim;
    dfs(0);
    cout << res << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

int W, H;
int field[20][20];
int field2[21][21];
int res;
const int dy[] = {-1, 0, 0, 1};
const int dx[] = {0, -1, 1, 0};
bool used[101][101];
int lim;

void fillField(int cy, int cx, int oldc, int newc, bool &ok, bool flag) {
  if (!flag)
    field[cy][cx] = newc;
  else
    field2[cy][cx] = newc;
  used[cy][cx] = true;
  for (int i = 0; i < 4; i++) {
    int ny = cy + dy[i];
    int nx = cx + dx[i];
    if (ny >= 0 && nx >= 0 && ny < H && nx < W && !used[ny][nx]) {
      if (!flag) {
        if (field[ny][nx] == oldc)
          fillField(ny, nx, oldc, newc, ok, flag);
        else if (field[ny][nx] == newc)
          ok = true;
      } else {
        if (field2[ny][nx] == oldc)
          fillField(ny, nx, oldc, newc, ok, flag);
        else if (field2[ny][nx] == newc)
          ok = true;
      }
    }
  }
}
void dfs(int cnt) {
  if (lim <= cnt)
    return;
  {
    int goal = field[0][0];
    bool ok = true;
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++)
        if (field[i][j] != goal)
          ok = false;
    if (ok) {
      res = min(res, cnt);
      return;
    }
  }
  for (int i = 0; i < 3; i++) {
    if (field[0][0] == i)
      continue;
    int backUp[20][20];
    for (int j = 0; j < H; j++)
      for (int k = 0; k < W; k++)
        backUp[j][k] = field[j][k];
    bool ok = false;
    // 塗りつぶし
    memset(used, 0, sizeof(used));
    fillField(0, 0, field[0][0], i, ok, false);
    // もし一つ以上属する色が増えるならdfs
    if (ok)
      dfs(cnt + 1);
    for (int j = 0; j < H; j++)
      for (int k = 0; k < W; k++)
        field[j][k] = backUp[j][k];
  }
}
int greedy() {
  {
    int goal = field2[0][0];
    bool ok = true;
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++)
        if (field2[i][j] != goal)
          ok = false;
    if (ok)
      return 0;
  }
  for (int i = 0; i < 3; i++) {
    if (field2[0][0] == i)
      continue;
    bool ok = false;
    // 塗りつぶし
    fillField(0, 0, field2[0][0], i, ok, true);
    // もし一つ以上属する色が増えるならdfs
    if (ok)
      return greedy() + 1;
  }
}

int main() {
  while (cin >> W >> H && (W | H)) {
    res = H * W;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        char ch;
        cin >> ch;
        if (ch == 'R')
          field[i][j] = 0;
        else if (ch == 'G')
          field[i][j] = 1;
        else if (ch == 'B')
          field[i][j] = 2;
        field2[i][j] = field[i][j];
      }
    }
    lim = greedy();
    res = lim;
    dfs(0);
    cout << res << endl;
  }
  return 0;
}