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

#include <bitset>
#include <cmath>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

int dx[] = {-1, -1, 0};
int dy[] = {-1, 0, 0};

typedef bitset<100> Panels;

int W, H, field[10][10];
vector<Panels> carpets[10][10];
int dp[10][10];

bool canCover(int x, int y, int s) {
  for (int i = y; i < y + s; i++)
    for (int j = x; j < x + s; j++)
      if (field[j][i] == 0)
        return false;

  return true;
}

Panels calcCovered(int x, int y, int s) {
  Panels res;
  for (int i = y; i < y + s; i++)
    for (int j = x; j < x + s; j++) {
      res.set(j + i * W, 1);
    }

  return res;
}

pair<Panels, int> calcInit(Panels &flawless) {
  int num = 0;
  Panels res = flawless;

  int cnt[100] = {0};
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (carpets[j][i].size() == 0)
        continue;
      for (int k = 0; k < 100; k++)
        if (carpets[j][i][0][k])
          cnt[k]++;
    }

  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (carpets[j][i].size() == 0)
        continue;
      for (int k = 0; k < 100; k++) {
        if (carpets[j][i][0][k] && cnt[k] == 1) {
          res |= carpets[j][i][0];
          carpets[j][i].clear();
          ++num;
          break;
        }
      }
    }

  return make_pair(res, num);
}

void remove(int x, int y) {
  if (carpets[x][y].size() == 0)
    return;

  int S = (int)sqrt(carpets[x][y][0].count());
  for (int i = y; i < y + S; i++)
    for (int j = x; j < x + S; j++) {
      if (j == x && i == y)
        continue;
      if (carpets[j][i].size() == 0)
        continue;

      int T = (int)sqrt(carpets[j][i][0].count());
      if (x + S >= j + T && y + S >= i + T) {
        carpets[j][i].clear();
      }
    }
}

int ans;
void dfs(int x, int y, int u, Panels f) {
  if (f.count() == W * H) {
    ans = u;
    return;
  }

  if (u + 1 >= ans)
    return;

  if (y == H)
    return;

  int tx = x + 1;
  int ty = y;

  if (tx == W) {
    tx = 0;
    ty++;
  }
  int S = carpets[x][y].size();

  if (f[x + y * W])
    dfs(tx, ty, u, f);

  for (int i = 0; i < S; i++) {
    Panels &c = carpets[x][y][i];
    Panels t = f;
    t |= c;

    if (t != f) {
      dfs(tx, ty, u + 1, t);
    } else
      break;
  }
}

int main() {
  while (cin >> W >> H, (W || H)) {
    Panels init;
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++) {
        cin >> field[j][i];
        carpets[j][i].clear();
        dp[j][i] = 1;

        if (field[j][i] == 0)
          init.set(j + i * W, 1);
      }

    int S = min(W, H);
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++) {
        int M = 1;
        for (int k = 0; k < 3; k++) {
          int tx = j + dx[k], ty = i + dy[k];
          if (tx < 0 || ty < 0)
            continue;
          dp[j][i] = max(dp[j][i], dp[tx][ty] - 1);

          if (carpets[tx][ty].size() != 0)
            dp[j][i] = max(dp[j][i], (int)sqrt(carpets[tx][ty][0].count()) - 1);
        }
        for (int k = S; k >= dp[j][i]; k--) {
          if (i + k > H || j + k > W)
            continue;
          if (canCover(j, i, k)) {
            carpets[j][i].push_back(calcCovered(j, i, k));
            break;
          }
        }
      }

    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++) {
        remove(j, i);
      }

    pair<Panels, int> in = calcInit(init);

    init = in.first;
    ans = (1 << 24);
    dfs(0, 0, in.second, init);

    cout << ans << endl;
  }
}

Error: TLE

Fixed submission:

#include <bitset>
#include <cmath>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

int dx[] = {-1, -1, 0};
int dy[] = {-1, 0, 0};

typedef bitset<100> Panels;

int W, H, field[100][100];
vector<Panels> carpets[100][100];
int dp[100][100];

bool canCover(int x, int y, int s) {
  for (int i = y; i < y + s; i++)
    for (int j = x; j < x + s; j++)
      if (field[j][i] == 0)
        return false;

  return true;
}

Panels calcCovered(int x, int y, int s) {
  Panels res;
  for (int i = y; i < y + s; i++)
    for (int j = x; j < x + s; j++) {
      res.set(j + i * W, 1);
    }

  return res;
}

void remove(int x, int y) {
  if (carpets[x][y].size() == 0)
    return;

  int S = (int)sqrt(carpets[x][y][0].count());
  for (int i = y; i < y + S; i++)
    for (int j = x; j < x + S; j++) {
      if (j == x && i == y)
        continue;
      if (carpets[j][i].size() == 0)
        continue;

      int T = (int)sqrt(carpets[j][i][0].count());
      if (x + S >= j + T && y + S >= i + T) {
        carpets[j][i].clear();
      }
    }
}

int ans;
void dfs(int x, int y, int u, Panels f) {
  if (f.count() == W * H) {
    ans = u;
    return;
  }

  if (u + 1 >= ans)
    return;

  if (y == H)
    return;

  int tx = x + 1;
  int ty = y;

  if (tx == W) {
    tx = 0;
    ty++;
  }
  int S = carpets[x][y].size();

  if (f[x + y * W])
    dfs(tx, ty, u, f);

  for (int i = 0; i < S; i++) {
    Panels &c = carpets[x][y][i];
    Panels t = f;
    t |= c;

    if (t != f) {
      dfs(tx, ty, u + 1, t);
    } else
      break;
  }
}

int main() {
  while (cin >> W >> H, (W || H)) {
    Panels init;
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++) {
        cin >> field[j][i];
        carpets[j][i].clear();
        dp[j][i] = 1;

        if (field[j][i] == 0)
          init.set(j + i * W, 1);
      }

    int S = min(W, H);
    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++) {
        int M = 1;
        for (int k = 0; k < 3; k++) {
          int tx = j + dx[k], ty = i + dy[k];
          if (tx < 0 || ty < 0)
            continue;
          dp[j][i] = max(dp[j][i], dp[tx][ty] - 1);

          if (carpets[tx][ty].size() != 0)
            dp[j][i] = max(dp[j][i], (int)sqrt(carpets[tx][ty][0].count()) - 1);
        }
        for (int k = S; k >= dp[j][i]; k--) {
          if (i + k > H || j + k > W)
            continue;
          if (canCover(j, i, k)) {
            carpets[j][i].push_back(calcCovered(j, i, k));
            break;
          }
        }
      }

    for (int i = 0; i < H; i++)
      for (int j = 0; j < W; j++) {
        remove(j, i);
      }

    ans = (1 << 24);
    dfs(0, 0, 0, init);

    cout << ans << endl;
  }
}