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

#include <iostream>
#include <sstream>
#include <string.h>
#include <string>
#include <vector>
using namespace std;
#define abs(a) ((a) < 0 ? -(a) : (a))

int pattern_small[] = {0, 1, 0, 1, 1, 1, 0, 1, 0};

int pattern_med[] = {1, 1, 1, 1, 1, 1, 1, 1, 1};

int pattern_big[] = {0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1,
                     1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0};

int mat[12][12];
int used[12][12][5];

bool lastCheck() {
  for (int y = 0; y < 10; y++)
    for (int x = 0; x < 10; x++) {
      if (mat[y][x] != 0) {
        return false;
      }
    }
  return true;
}

bool putValid(int y, int x, int off_y, int off_x, int h, int w, int *pattern) {
  int sy = y - off_y;
  int sx = x - off_x;
  int ty = sy + h - 1;
  int tx = sx + w - 1;
  if (sy < 0 || sx < 0 || ty >= 10 || tx >= 10)
    return false;

  for (int i = 0; i < h; i++)
    for (int j = 0; j < w; j++) {
      int ny = sy + i;
      int nx = sx + j;
      if (pattern[i * w + j] == 1 && (mat[ny][nx] <= 0)) {
        return false;
      }
    }

  return true;
}

bool allow(int n) {
  for (int i = 0; i < n; i++) {
    int sy = i / 10;
    int sx = i % 10;
    if (mat[sy][sx] == 0)
      continue;

    bool ok = false;
    for (int j = n; j < 100; j++) {
      int ty = j / 10;
      int tx = j % 10;
      int dy = abs(sy - ty);
      int dx = abs(sx - tx);

      if (dy >= 3)
        break;
      if (dy + dx <= 1 && putValid(ty, tx, 1, 1, 3, 3, pattern_small)) {
        ok = true;
        break;
      }
      if (dy <= 1 && dx <= 1 && putValid(ty, tx, 1, 1, 3, 3, pattern_med)) {
        ok = true;
        break;
      }
      if (dy + dx <= 2 && putValid(ty, tx, 2, 2, 5, 5, pattern_big)) {
        ok = true;
        break;
      }
    }

    if (!ok)
      return false;
  }
  return true;
}

bool update(int y, int x, int off_y, int off_x, int h, int w, int *pattern,
            int num) {
  int sy = y - off_y;
  int sx = x - off_x;
  int ty = sy + h - 1;
  int tx = sx + w - 1;
  if (sy < 0 || sx < 0 || ty >= 10 || tx >= 10)
    return false;

  for (int i = 0; i < h; i++)
    for (int j = 0; j < w; j++) {
      int ny = sy + i;
      int nx = sx + j;
      if (pattern[i * w + j] == 1) {
        if (mat[ny][nx] < num)
          return false;
        mat[ny][nx] -= num;
      }
    }

  return true;
}

bool dfs(int rest, int n) {
  if (rest == 0)
    return lastCheck();
  if (n >= 10 * 10)
    return false;
  if (!allow(n))
    return false;

  int y = n / 10;
  int x = n % 10;

  if (mat[y][x] == 0) {
    return dfs(rest, n + 1);
  }
  if (dfs(rest, n + 1)) {
    return true;
  }

  int temp[12][12];
  memcpy(temp, mat, sizeof(mat));

  for (int i = 0; i <= rest; i++) {
    for (int j = 0; j <= rest - i; j++) {
      for (int k = 0; k <= rest - i - j; k++) {
        int s = i + j + k;
        if (s == 0)
          continue;

        bool ok = true;
        if (ok && (i > 0) && !update(y, x, 1, 1, 3, 3, pattern_small, i))
          ok = false;
        if (ok && (j > 0) && !update(y, x, 1, 1, 3, 3, pattern_med, j))
          ok = false;
        if (ok && (k > 0) && !update(y, x, 2, 2, 5, 5, pattern_big, k))
          ok = false;

        if (ok) {
          used[y][x][1] = i;
          used[y][x][2] = j;
          used[y][x][3] = k;

          if (dfs(rest - s, n + 1)) {
            return true;
          }

          used[y][x][1] = 0;
          used[y][x][2] = 0;
          used[y][x][3] = 0;
        }

        memcpy(mat, temp, sizeof(temp));
      }
    }
  }

  return false;
}

int main() {

  int K;
  cin >> K;

  for (int y = 0; y < 10; y++)
    for (int x = 0; x < 10; x++)
      cin >> mat[y][x];
  if (!dfs(K, 0)) {
    cout << "WA" << endl;
  }

  for (int y = 0; y < 10; y++)
    for (int x = 0; x < 10; x++) {
      for (int k = 1; k <= 3; k++) {
        int cnt = used[y][x][k];
        for (int t = 0; t < cnt; t++) {
          cout << x << " " << y << " " << k << endl;
        }
      }
    }

  return 0;
}

Error: TLE

Fixed submission:

#include <iostream>
#include <sstream>
#include <string.h>
#include <string>
#include <vector>
using namespace std;

int pattern_small[] = {0, 1, 0, 1, 1, 1, 0, 1, 0};

int pattern_med[] = {1, 1, 1, 1, 1, 1, 1, 1, 1};

int pattern_big[] = {0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1,
                     1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0};

int mat[12][12];
int used[12][12][5];

inline int valid(int y, int x, int off_y, int off_x, int h, int w,
                 int *pattern) {
  int sy = y - off_y;
  int sx = x - off_x;
  if (sy < 0 || sx < 0)
    return false;
  int mini = 1000;
  for (int i = 0; i < h; i++)
    for (int j = 0; j < w; j++) {
      int ny = sy + i;
      int nx = sx + j;
      if (pattern[i * w + j]) {
        mini = min(mini, mat[ny][nx]);
      }
    }
  return mini;
}

inline void update(int y, int x, int off_y, int off_x, int h, int w,
                   int *pattern) {
  int sy = y - off_y;
  int sx = x - off_x;
  for (int i = 0; i < h; i++)
    for (int j = 0; j < w; j++) {
      int ny = sy + i;
      int nx = sx + j;
      if (pattern[i * w + j])
        mat[ny][nx]--;
    }
}

bool lastCheck() {
  for (int y = 0; y < 10; y++)
    for (int x = 0; x < 10; x++) {
      if (mat[y][x] != 0)
        return false;
    }
  return true;
}

bool nowValid(int y, int x) {
  static int dy[] = {0, 0, 1, 1, 1, 2};
  static int dx[] = {1, 2, -1, 0, 1, 0};
  for (int i = 0; i < 6; i++) {
    int ny = y + dy[i];
    int nx = x + dx[i];
    if (ny < 0 || ny >= 10 || nx < 0 || nx >= 10)
      continue;
    if (mat[ny][nx] > 0)
      return true;
  }
  return false;
}

bool dfs(int k, int n, int last) {
  if (k == 0)
    return lastCheck();
  if (n >= 10 * 10)
    return false;

  int y = n / 10;
  int x = n % 10;

  int temp[12][12];

  if (mat[y][x] > 0) {
    if (1 > last) {
      int mini = min(k, valid(y, x, 1, 1, 3, 3, pattern_small));
      if (mini > 0) {
        memcpy(temp, mat, sizeof(mat));
        for (int i = 1; i <= mini; i++) {
          used[y][x][1] = i;
          update(y, x, 1, 1, 3, 3, pattern_small);
          if (dfs(k - i, n, 1)) {
            return true;
          }
        }
        used[y][x][1] = 0;
        memcpy(mat, temp, sizeof(temp));
      }
    }

    if (2 > last) {
      int mini = min(k, valid(y, x, 1, 1, 3, 3, pattern_med));
      if (mini > 0) {
        memcpy(temp, mat, sizeof(mat));
        for (int i = 1; i <= mini; i++) {
          used[y][x][2] = i;
          update(y, x, 1, 1, 3, 3, pattern_med);
          if (dfs(k - i, n, 2)) {
            return true;
          }
        }
        used[y][x][2] = 0;
        memcpy(mat, temp, sizeof(temp));
      }
    }

    if (3 > last) {
      int mini = min(k, valid(y, x, 2, 2, 5, 5, pattern_big));
      if (mini > 0) {
        memcpy(temp, mat, sizeof(mat));
        for (int i = 1; i <= mini; i++) {
          used[y][x][3] = i;
          update(y, x, 2, 2, 5, 5, pattern_big);
          if (dfs(k - i, n + 1, 0)) {
            return true;
          }
        }
        used[y][x][3] = 0;
        memcpy(mat, temp, sizeof(temp));
      }
    }

    if (!nowValid(y, x)) {
      return false;
    }
  }

  return dfs(k, n + 1, 0);
}

int main() {

  int K;
  cin >> K;

  for (int y = 0; y < 10; y++)
    for (int x = 0; x < 10; x++)
      cin >> mat[y][x];
  if (!dfs(K, 0, 1)) {
    int k = 0;
    int n = 10 / k;
    cout << n << endl;
    return 0;
  }

  for (int y = 0; y < 10; y++)
    for (int x = 0; x < 10; x++) {
      for (int k = 1; k <= 3; k++) {
        for (int t = 0; t < used[y][x][k]; t++) {
          cout << x << " " << y << " " << k << endl;
        }
      }
    }
  return 0;
}