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

#include <cstdlib>
#include <iostream>
#include <list>
#include <ostream>
#include <stack>
#include <vector>
using namespace std;

enum tag_drop_sizes { small_drop = 1, middle_drop, large_drop };

static const int MARGIN = 2;
static const int BIAS = 2;
static const int H = 10, W = 10;

const int small[5][5] = {{0, 0, 0, 0, 0},
                         {0, 0, 1, 0, 0},
                         {0, 1, 1, 1, 0},
                         {0, 0, 1, 0, 0},
                         {0, 0, 0, 0, 0}};
const int middle[5][5] = {{0, 0, 0, 0, 0},
                          {0, 1, 1, 1, 0},
                          {0, 1, 1, 1, 0},
                          {0, 1, 1, 1, 0},
                          {0, 0, 0, 0, 0}};
const int large[5][5] = {{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}};

const int small_size = 5, middle_size = 9, large_size = 13;

struct operation {
  int x;
  int y;
  int size;

  operation(int a, int b, int c) {
    x = a;
    y = b;
    size = c;
  }
};

struct cell_info {
  int x, y;
  int size;
  int n;

  cell_info(int a, int b, int c, int d) {
    x = a;
    y = b;
    size = c;
    n = d;
  }
};

int cloth[16][16];
int depth;
int total;
int num_large_drop, num_middle_drop, num_small_drop;
stack<operation> s;
list<cell_info> lst;

bool add(int x, int y, const int drop_size[5][5]) {
  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
      cloth[y + i + MARGIN - BIAS][x + j + MARGIN - BIAS] += drop_size[i][j];
    }
  }
  return true;
}

bool sub(int x, int y, const int drop_size[5][5]) {
  bool ret = true;
  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
      if ((cloth[y + i + MARGIN - BIAS][x + j + MARGIN - BIAS] -=
           drop_size[i][j]) < 0)
        ret = false;
    }
  }
  return ret;
}

void init() {
  depth = 0;
  for (int i = 0; i < 16; i++)
    for (int j = 0; j < 16; j++)
      cloth[i][j] = 0;
}

bool complete() {
  for (int i = 0; i < 16; i++)
    for (int j = 0; j < 16; j++)
      if (cloth[i][j])
        return false;
  return true;
}

bool alone(const int x, const int y) {
  for (int i = x + MARGIN - BIAS; i < x + MARGIN - BIAS + 5; i++) {
    for (int j = y + MARGIN - BIAS; j < y + MARGIN - BIAS + 5; j++) {
      if (cloth[i][j] && (!cloth[i - 1][j] && !cloth[i + 1][j] &&
                          !cloth[i][j - 1] && !cloth[i][j + 1]))
        return true;
    }
  }

  return false;
}

bool solve(list<cell_info>::iterator p) {

  if (depth == 0)
    return complete();

  else if (p == lst.end())
    return false;

  /* large drop case */
  if (p->size == large_drop && num_large_drop > 0 && p->n > 0) {
    if (sub(p->x, p->y, large)) {
      if (!alone(p->x, p->y)) {
        s.push(operation(p->x, p->y, large_drop));
        num_large_drop--;
        depth--;
        p->n--;
        if (solve(p))
          return true;
        p->n++;
        depth++;
        num_large_drop++;
        s.pop();
      }
    }
    add(p->x, p->y, large);
  }

  /* middle drop case */
  if (p->size == middle_drop && num_middle_drop > 0 && p->n > 0) {
    if (sub(p->x, p->y, middle)) {
      if (!alone(p->x, p->y)) {
        s.push(operation(p->x, p->y, middle_drop));
        num_middle_drop--;
        depth--;
        p->n--;
        if (solve(p))
          return true;
        p->n++;
        depth++;
        num_middle_drop++;
        s.pop();
      }
    }
    add(p->x, p->y, middle);
  }

  /* small drop case */
  if (p->size == small_drop && num_small_drop > 0 && p->n > 0) {
    if (sub(p->x, p->y, small)) {
      if (!alone(p->x, p->y)) {
        s.push(operation(p->x, p->y, small_drop));
        num_small_drop--;
        depth--;
        p->n--;
        if (solve(p))
          return true;
        p->n++;
        depth++;
        num_small_drop++;
        s.pop();
      }
    }
    add(p->x, p->y, small);
  }

  /* no drop */
  return solve(++p);
}

int count_total() {
  int count = 0;
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      count += cloth[MARGIN + i][MARGIN + j];
    }
  }

  return count;
}

bool set_num() {
  static int i = 0, j = 0;
  for (; i <= depth; i++, j = 0) {
    for (; j <= depth - i; j++) {
      if (4 * i + 8 * j == total - 5 * depth) {
        num_small_drop = depth - i - j;
        num_middle_drop = i;
        num_large_drop = j;

        j++;
        return true;
      }
    }
  }

  return false;
}

void make_lst() {
  int tmp[16][16];
  for (int i_ = 0; i_ < 16; i_++)
    for (int j_ = 0; j_ < 16; j_++)
      tmp[i_][j_] = cloth[i_][j_];

  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      cell_info tmp_s(i, j, small_drop, 0), tmp_m(i, j, middle_drop, 0),
          tmp_l(i, j, large_drop, 0);

      while (sub(i, j, large)) {
        tmp_s.n++;
        tmp_m.n++;
        tmp_l.n++;
      }
      add(i, j, large);
      while (sub(i, j, middle)) {
        tmp_s.n++;
        tmp_m.n++;
      }
      add(i, j, middle);
      while (sub(i, j, small)) {
        tmp_s.n++;
      }
      add(i, j, small);

      // restore
      for (int i_ = 0; i_ < 16; i_++)
        for (int j_ = 0; j_ < 16; j_++)
          cloth[i_][j_] = tmp[i_][j_];

      if (tmp_l.n != 0)
        lst.push_back(tmp_l);
      if (tmp_m.n != 0)
        lst.push_back(tmp_m);
      if (tmp_s.n != 0)
        lst.push_back(tmp_s);
    }
  }
}

bool remove_lst() {
  list<list<cell_info>::iterator> table[10][10];

  for (list<cell_info>::iterator p = lst.begin(); p != lst.end(); p++) {
    if (p->size >= small_drop) {
      table[p->y][p->x].push_back(p);
      table[p->y][p->x - 1].push_back(p);
      table[p->y][p->x + 1].push_back(p);
      table[p->y - 1][p->x].push_back(p);
      table[p->y + 1][p->x].push_back(p);
    }
    if (p->size >= middle_drop) {
      table[p->y - 1][p->x - 1].push_back(p);
      table[p->y - 1][p->x + 1].push_back(p);
      table[p->y + 1][p->x - 1].push_back(p);
      table[p->y + 1][p->x + 1].push_back(p);
    }
    if (p->size >= large_drop) {
      table[p->y - 2][p->x].push_back(p);
      table[p->y + 2][p->x].push_back(p);
      table[p->y][p->x - 2].push_back(p);
      table[p->y][p->x + 2].push_back(p);
    }
  }

  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      if (table[i][j].size() == 1) {
        list<cell_info>::iterator p = *table[i][j].begin();
        s.push(operation(p->x, p->y, p->size));
        if (p->size == large_drop) {
          sub(p->x, p->y, large);
        } else if (p->size == middle_drop) {
          sub(p->x, p->y, middle);
        } else {
          sub(p->x, p->y, small);
        }
        lst.erase(p);
        depth--;
        return true;
      }
    }
  }

  return false;
}

int main() {
  int copy[16][16];
  init();
  cin >> depth;
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      cin >> cloth[i + MARGIN][j + MARGIN];
    }
  }

  if (depth == 0)
    return 0;

  do {
    lst.clear();
    make_lst();
  } while (remove_lst());

  total = count_total();
  for (int i = 0; i < 16; i++) {
    for (int j = 0; j < 16; j++) {
      copy[i][j] = cloth[i][j];
    }
  }

  while (1) {
    if (!set_num())
      break;
    if (solve(lst.begin())) {
      break;
    }

    for (int i = 0; i < 16; i++) {
      for (int j = 0; j < 16; j++) {
        cloth[i][j] = copy[i][j];
      }
    }
  }

  while (!s.empty()) {
    operation tmp = s.top();
    cout << tmp.x << " " << tmp.y << " " << tmp.size << endl;
    s.pop();
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <cstdlib>
#include <iostream>
#include <list>
#include <ostream>
#include <stack>
#include <vector>
using namespace std;

enum tag_drop_sizes { small_drop = 1, middle_drop, large_drop };

static const int MARGIN = 2;
static const int H = 10, W = 10;

const int small[5][5] = {{0, 0, 0, 0, 0},
                         {0, 0, 1, 0, 0},
                         {0, 1, 1, 1, 0},
                         {0, 0, 1, 0, 0},
                         {0, 0, 0, 0, 0}};
const int middle[5][5] = {{0, 0, 0, 0, 0},
                          {0, 1, 1, 1, 0},
                          {0, 1, 1, 1, 0},
                          {0, 1, 1, 1, 0},
                          {0, 0, 0, 0, 0}};
const int large[5][5] = {{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}};

const int small_size = 5, middle_size = 9, large_size = 13;

struct operation {
  int x;
  int y;
  int size;

  operation(int a, int b, int c) {
    x = a;
    y = b;
    size = c;
  }
};

struct cell_info {
  int x, y;
  int size;
  int n;

  cell_info(int a, int b, int c, int d) {
    x = a;
    y = b;
    size = c;
    n = d;
  }
};

int cloth[16][16];
int depth;
int total;
int num_large_drop, num_middle_drop, num_small_drop;
stack<operation> s;
list<cell_info> lst;

bool add(int x, int y, const int drop_size[5][5]) {
  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
      cloth[y + i][x + j] += drop_size[i][j];
    }
  }
  return true;
}

bool sub(int x, int y, const int drop_size[5][5]) {
  bool ret = true;
  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
      if ((cloth[y + i][x + j] -= drop_size[i][j]) < 0)
        ret = false;
    }
  }
  return ret;
}

void init() {
  depth = 0;
  for (int i = 0; i < 16; i++)
    for (int j = 0; j < 16; j++)
      cloth[i][j] = 0;
}

bool complete() {
  for (int i = 0; i < 16; i++)
    for (int j = 0; j < 16; j++)
      if (cloth[i][j])
        return false;
  return true;
}

bool alone() {
  for (int i = MARGIN; i < 10 + MARGIN; i++) {
    for (int j = MARGIN; j < 10 + MARGIN; j++) {
      if (cloth[i][j] && (!cloth[i - 1][j] && !cloth[i + 1][j] &&
                          !cloth[i][j - 1] && !cloth[i][j + 1]))
        return true;
    }
  }

  return false;
}

bool solve(list<cell_info>::iterator p) {

  if (depth == 0)
    return complete();

  else if (p == lst.end())
    return false;

  /* large drop case */
  if (num_large_drop > 0 && p->size == large_drop && p->n > 0) {
    if (sub(p->x, p->y, large)) {
      if (!alone()) {
        s.push(operation(p->x, p->y, large_drop));
        num_large_drop--;
        depth--;
        p->n--;
        if (solve(p))
          return true;
        p->n++;
        depth++;
        num_large_drop++;
        s.pop();
      }
    }
    add(p->x, p->y, large);
  }

  /* middle drop case */
  if (num_middle_drop > 0 && p->size == middle_drop && p->n > 0) {
    if (sub(p->x, p->y, middle)) {
      if (!alone()) {
        s.push(operation(p->x, p->y, middle_drop));
        num_middle_drop--;
        depth--;
        p->n--;
        if (solve(p))
          return true;
        p->n++;
        depth++;
        num_middle_drop++;
        s.pop();
      }
    }
    add(p->x, p->y, middle);
  }

  /* small drop case */
  if (num_small_drop > 0 && p->size == small_drop && p->n > 0) {
    if (sub(p->x, p->y, small)) {
      if (!alone()) {
        s.push(operation(p->x, p->y, small_drop));
        num_small_drop--;
        depth--;
        p->n--;
        if (solve(p))
          return true;
        p->n++;
        depth++;
        num_small_drop++;
        s.pop();
      }
    }
    add(p->x, p->y, small);
  }

  /* no drop */
  return solve(++p);
}

int count_total() {
  int count = 0;
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      count += cloth[MARGIN + i][MARGIN + j];
    }
  }

  return count;
}

void set_num() {
  static int i = 0, j = 0;
  for (; i <= depth; i++, j = 0) {
    for (; j <= depth - i; j++) {
      if (4 * i + 8 * j == total - 5 * depth) {
        num_small_drop = depth - i - j;
        num_middle_drop = i;
        num_large_drop = j;

        j++;
        return;
      }
    }
  }
  exit(1);
}

void make_lst() {
  int tmp[16][16];
  for (int i_ = 0; i_ < 16; i_++)
    for (int j_ = 0; j_ < 16; j_++)
      tmp[i_][j_] = cloth[i_][j_];

  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      cell_info tmp_s(i, j, small_drop, 0), tmp_m(i, j, middle_drop, 0),
          tmp_l(i, j, large_drop, 0);

      while (sub(i, j, large)) {
        tmp_s.n++;
        tmp_m.n++;
        tmp_l.n++;
      }
      add(i, j, large);
      while (sub(i, j, middle)) {
        tmp_s.n++;
        tmp_m.n++;
      }
      add(i, j, middle);
      while (sub(i, j, small)) {
        tmp_s.n++;
      }
      add(i, j, small);

      // restore
      for (int i_ = 0; i_ < 16; i_++)
        for (int j_ = 0; j_ < 16; j_++)
          cloth[i_][j_] = tmp[i_][j_];

      if (tmp_l.n != 0)
        lst.push_back(tmp_l);
      if (tmp_m.n != 0)
        lst.push_back(tmp_m);
      if (tmp_s.n != 0)
        lst.push_back(tmp_s);
    }
  }
}

int main() {
  int copy[16][16];
  init();
  cin >> depth;
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      cin >> cloth[i + MARGIN][j + MARGIN];
    }
  }

  for (int i = 0; i < 16; i++) {
    for (int j = 0; j < 16; j++) {
      copy[i][j] = cloth[i][j];
    }
  }

  if (depth == 0)
    return 0;

  total = count_total();
  make_lst();

  while (1) {
    set_num();
    if (solve(lst.begin())) {
      while (!s.empty()) {
        operation tmp = s.top();
        cout << tmp.x << " " << tmp.y << " " << tmp.size << endl;
        s.pop();
      }
      break;
    }

    for (int i = 0; i < 16; i++) {
      for (int j = 0; j < 16; j++) {
        cloth[i][j] = copy[i][j];
      }
    }
  }

  return 0;
}