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

#include <algorithm>
#include <bitset>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

vector<string> puzzle_flame;
int puzzle_size;
int puzzle_w;
int puzzle_h;
int piece_num;

struct piece {
  vector<vector<string>> p;
  int size;
  vector<int> sharp_x;
  vector<int> sharp_y;
  bitset<4> same_flg;
  piece() {}
  piece(vector<string> v) {
    // make rotate piece {{{
    vector<string> tmp;

    p.push_back(v);

    for (int i = 0; i < v[0].size(); i++) {
      string s = "";
      for (int j = 0; j < v.size(); j++) {
        s += v[j][v[0].size() - 1 - i];
      }
      tmp.push_back(s);
    }
    p.push_back(tmp);

    tmp.clear();
    for (int i = 0; i < v.size(); i++) {
      string s = "";
      for (int j = 0; j < v[i].size(); j++) {
        s += v[v.size() - 1 - i][v[0].size() - 1 - j];
      }
      tmp.push_back(s);
    }
    p.push_back(tmp);

    tmp.clear();
    for (int i = 0; i < v[0].size(); i++) {
      string s = "";
      for (int j = 0; j < v.size(); j++) {
        s += v[v.size() - 1 - j][i];
      }
      tmp.push_back(s);
    }
    p.push_back(tmp);
    // }}}
    // init size {{{
    size = 0;
    for (int i = 0; i < v.size(); i++) {
      for (int j = 0; j < v[i].size(); j++) {
        size += v[i][j] == '#';
      }
    }
    // }}}
    // make sharp_x,y {{{
    for (int i = 0; i < p.size(); i++) {
      for (int j = 0; j < p[i].size(); j++) {
        for (int k = 0; k < p[i][j].size(); k++) {
          if (p[i][j][k] == '#') {
            sharp_y.push_back(j);
            sharp_x.push_back(k);
            goto exit_mk_sharp;
          }
        }
      }
    exit_mk_sharp:;
    }
    // }}}
    for (int i = 0; i < p.size(); i++) {
      same_flg[i] = false;
      for (int j = 0; j < i; j++) {
        if (p[i].size() == p[j].size()) {
          bool flg = true;
          for (int k = 0; k < p[i].size(); k++) {
            for (int l = 0; l < p[i][k].size(); l++) {
              if (p[i][k][l] != p[j][k][l]) {
                flg = false;
              }
            }
          }
          if (flg)
            same_flg[i] = true;
        }
      }
    }
  }
};

vector<piece> usable_pieces;

bitset<64> interference[40][40][64];
const int margin = 32;
// piece a, b, bias Y b - a, bias X b - a
void set_interference() { // {{{
  for (int i = 0; i < usable_pieces.size() * 4; i++) {
    const vector<string> a = usable_pieces[i >> 2].p[i & 0x3];
    for (int j = 0; j < usable_pieces.size() * 4; j++) {
      const vector<string> b = usable_pieces[j >> 2].p[j & 0x3];

      //	cout << i << "," << j << endl;
      //	cout << (i >> 2) << "," << (i & 0x3) << " " << (j >> 2) << ","
      //<< (j & 0x3) << endl;

      if ((i >> 2) == (j >> 2)) {
        for (int bias_i = 0; bias_i < 64; bias_i++) {
          for (int bias_j = 0; bias_j < 64; bias_j++) {
            interference[i][j][bias_i][bias_j] = false;
          }
        }
        continue;
      }

      for (int bias_i = -25; bias_i <= 25; bias_i++) {
        for (int bias_j = -25; bias_j <= 25; bias_j++) {
          bool f = true;
          for (int i_ = max(0, bias_i);
               i_ < min((int)a.size(), (int)b.size() + bias_i); i_++) {
            for (int j_ = max(0, bias_j);
                 j_ < min((int)a[0].size(), (int)b[0].size() + bias_j); j_++) {
              if ((a[i_][j_] == '#') && (b[i_ - bias_i][j_ - bias_j] == '#'))
                f = false;
            }
          }
          if (f)
            interference[i][j][margin + bias_i].set(margin + bias_j);
          else {
            interference[i][j][margin + bias_i].reset(margin + bias_j);
          }
        }
      }
    }
  }
  // }}}
}

bitset<20> put[40][20];
void set_put() { // {{{
  for (int i = 0; i < usable_pieces.size() * 4; i++) {
    const vector<string> a = usable_pieces[i >> 2].p[i & 0x3];
    for (int j = 0; j < puzzle_h; j++) {
      for (int k = 0; k < puzzle_w; k++) {
        if (j + a.size() > puzzle_h || k + a[0].size() > puzzle_w) {
          break;
        }

        bool f = true;
        for (int j_ = 0; j_ < a.size(); j_++) {
          for (int k_ = 0; k_ < a[j_].size(); k_++) {
            if (puzzle_flame[j + j_][k + k_] == '#' && a[j_][k_] == '#')
              f = false;
          }
        }

        if (f)
          put[i][j].set(k);
        else
          put[i][j].reset(k);
      }
    }
  }
  // cout << endl;
  // }}}
}

int piece_list;
struct position {
  int x, y;
  int n;
  position(int x_, int y_, int n_) {
    x = x_;
    y = y_;
    n = n_;
  }
};
vector<position> use;
int use_flgs;

bool solve(int y, int x) {
  /*
  cout << endl;
  for(int i = 0; i < puzzle_h; i++) {
          cout << puzzle_flame[i] << endl;
  } cout << endl;
  for(int i = 0; i < 10; i++)
          cout << (((piece_list^use_flgs) & (1 << i)) ? '1' : '0');
  cout << endl;
  for(int i = 0; i < puzzle_h; i++) {
          for(int j = 0; j < puzzle_w; j++) {
                  if(puzzle_flame[i][j] == '*')
                          puzzle_flame[i][j] = '#';
          }
  }
  // */
  if (!(piece_list ^ use_flgs))
    return true;
  for (int i = 0; i < puzzle_h; i++) {
    for (int j = 0; j < puzzle_w; j++) {
      if (puzzle_flame[i][j] == '.') {
        //	cout << "i,j:" << i << "," << j << endl;
        for (int k = 0; k < piece_num; k++) {
          if ((piece_list ^ use_flgs) & (1 << k)) {
            for (int l = 0; l < 4; l++) {
              if (usable_pieces[k].same_flg[l]) {
                continue;
              }
              int X, Y;
              Y = i - usable_pieces[k].sharp_y[l];
              X = j - usable_pieces[k].sharp_x[l];
              //			cout << X << "," << Y << "," << k <<
              //endl;
              if (Y >= 0 && X >= 0 && put[(k << 2) + l][Y][X]) {
                bool call_flg = true;
                for (int m = 0; m < use.size(); m++) {
                  call_flg &= interference[(k << 2) + l][use[m].n]
                                          [margin + use[m].y - Y]
                                          [margin + use[m].x - X];
                  //	cout << use[m].y << "," << use[m].x << "," << use[m].n
                  //<< endl;
                }
                if (call_flg) {
                  int next_x, next_y;
                  next_x = (j + 1) % puzzle_w;
                  next_y = i + (j + 1) / puzzle_w;

                  for (int i_ = 0; i_ < usable_pieces[k].p[l].size(); i_++) {
                    for (int j_ = 0; j_ < usable_pieces[k].p[l][i_].size();
                         j_++) {
                      if (usable_pieces[k].p[l][i_][j_] == '#') {
                        /*
                        if(puzzle_flame[Y + i_][X + j_] == '#')
                                cout << "fail" << endl;
                        // */
                        puzzle_flame[Y + i_][X + j_] = '#';
                      }
                    }
                  }

                  use.push_back(position(X, Y, (k << 2) + l));
                  use_flgs |= 1 << k;

                  bool solve_res;
                  solve_res = solve(next_y, next_x);

                  for (int i_ = 0; i_ < usable_pieces[k].p[l].size(); i_++) {
                    for (int j_ = 0; j_ < usable_pieces[k].p[l][i_].size();
                         j_++) {
                      if (usable_pieces[k].p[l][i_][j_] == '#') {
                        puzzle_flame[Y + i_][X + j_] = '.';
                      }
                    }
                  }
                  use.pop_back();
                  use_flgs &= ~(1 << k);

                  if (solve_res)
                    return true;
                }
              }
            }
          }
        }

        return false;
      }
    }
  }
  return false;
}

void init_global_val() {
  puzzle_flame.clear();
  puzzle_size = 0;
  puzzle_w = 0;
  puzzle_h = 0;
  piece_num = 0;
  usable_pieces.clear();
  for (int i = 0; i < 40; i++) {
    for (int j = 0; j < 40; j++) {
      for (int k = 0; k < 64; k++) {
        for (int l = 0; l < 64; l++) {
          interference[i][j][k].set(l);
        }
      }
    }
  }
  piece_list = 0;
  use.clear();
  use_flgs = 0;
  for (int i = 0; i < 40; i++) {
    for (int j = 0; j < 20; j++) {
      for (int k = 0; k < 20; k++) {
        put[i][j].reset(k);
      }
    }
  }
}

void solve_init() {
  piece_list = 0;
  use_flgs = 0;
  use.clear();
}

int main() {
  init_global_val();
  while (cin >> puzzle_h >> puzzle_w, puzzle_h || puzzle_w) {
    // input puzzle {{{
    for (int i = 0; i < puzzle_h; i++) {
      string s;
      cin >> s;
      puzzle_flame.push_back(s);
    }
    cin >> piece_num;
    for (int i = 0; i < piece_num; i++) {
      int h, w;
      cin >> h >> w;
      vector<string> v;
      for (int j = 0; j < h; j++) {
        string s;
        cin >> s;
        v.push_back(s);
      }
      usable_pieces.push_back(piece(v));
    }
    // }}}
    // prepaire {{{
    puzzle_size = 0;
    for (int i = 0; i < puzzle_flame.size(); i++) {
      for (int j = 0; j < puzzle_flame[i].size(); j++) {
        puzzle_size += (puzzle_flame[i][j] == '.');
      }
    }

    // cout << puzzle_size << endl;

    set_interference();
    set_put();

    /*
    for(int i = 0; i < 4*usable_pieces.size(); i++) {
            cout << (i >> 2) << ":" << (i & 0x3) << endl;
            for(int j = 0; j < puzzle_h; j++) {
                    for(int k = 0; k < puzzle_w; k++) {
                            cout << (put[i][j][k] ? '.' : '@');
                    }
                    cout << endl;
            }
            cout << endl;
    }
    // */
    // }}}
    // query {{{
    int query_num;
    cin >> query_num;
    for (int q = 0; q < query_num; q++) {
      int n;
      cin >> n;
      solve_init();

      int sz = 0;
      for (int i = 0; i < n; i++) {
        int k;
        cin >> k;
        piece_list ^= (1 << (k - 1));
        sz += usable_pieces[k - 1].size;
      }

      /*
      if(puzzle_size != sz)
              cout << "size error:";
      // */
      if (puzzle_size == sz && solve(0, 0))
        cout << "YES" << endl;
      else
        cout << "NO" << endl;
    }
    // }}}
    init_global_val();
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

vector<string> puzzle_flame;
int puzzle_size;
int puzzle_w;
int puzzle_h;
int piece_num;

struct piece {
  vector<vector<string>> p;
  int size;
  vector<int> sharp_x;
  vector<int> sharp_y;
  piece() {}
  piece(vector<string> v) {
    // make rotate piece {{{
    vector<string> tmp;

    p.push_back(v);

    for (int i = 0; i < v[0].size(); i++) {
      string s = "";
      for (int j = 0; j < v.size(); j++) {
        s += v[j][v[0].size() - 1 - i];
      }
      tmp.push_back(s);
    }
    p.push_back(tmp);

    tmp.clear();
    for (int i = 0; i < v.size(); i++) {
      string s = "";
      for (int j = 0; j < v[i].size(); j++) {
        s += v[v.size() - 1 - i][v[0].size() - 1 - j];
      }
      tmp.push_back(s);
    }
    p.push_back(tmp);

    tmp.clear();
    for (int i = 0; i < v[0].size(); i++) {
      string s = "";
      for (int j = 0; j < v.size(); j++) {
        s += v[v.size() - 1 - j][i];
      }
      tmp.push_back(s);
    }
    p.push_back(tmp);
    // }}}
    // init size {{{
    size = 0;
    for (int i = 0; i < v.size(); i++) {
      for (int j = 0; j < v[i].size(); j++) {
        size += v[i][j] == '#';
      }
    }
    // }}}
    // make sharp_x,y {{{
    for (int i = 0; i < p.size(); i++) {
      for (int j = 0; j < p[i].size(); j++) {
        for (int k = 0; k < p[i][j].size(); k++) {
          if (p[i][j][k] == '#') {
            sharp_y.push_back(j);
            sharp_x.push_back(k);
            goto exit_mk_sharp;
          }
        }
      }
    exit_mk_sharp:;
    }
    // }}}
  }
};

vector<piece> usable_pieces;

bitset<64> interference[40][40][64];
const int margin = 32;
// piece a, b, bias Y b - a, bias X b - a
void set_interference() { // {{{
  for (int i = 0; i < usable_pieces.size() * 4; i++) {
    const vector<string> a = usable_pieces[i >> 2].p[i & 0x3];
    for (int j = 0; j < usable_pieces.size() * 4; j++) {
      const vector<string> b = usable_pieces[j >> 2].p[j & 0x3];

      //  cout << i << "," << j << endl;
      //  cout << (i >> 2) << "," << (i & 0x3) << " " << (j >> 2) << "," << (j &
      //  0x3) << endl;

      if ((i >> 2) == (j >> 2)) {
        for (int bias_i = 0; bias_i < 64; bias_i++) {
          for (int bias_j = 0; bias_j < 64; bias_j++) {
            interference[i][j][bias_i][bias_j] = false;
          }
        }
        continue;
      }

      for (int bias_i = -25; bias_i <= 25; bias_i++) {
        for (int bias_j = -25; bias_j <= 25; bias_j++) {
          bool f = true;
          for (int i_ = max(0, bias_i);
               i_ < min((int)a.size(), (int)b.size() + bias_i); i_++) {
            for (int j_ = max(0, bias_j);
                 j_ < min((int)a[0].size(), (int)b[0].size() + bias_j); j_++) {
              if ((a[i_][j_] == '#') && (b[i_ - bias_i][j_ - bias_j] == '#'))
                f = false;
            }
          }
          if (f)
            interference[i][j][margin + bias_i].set(margin + bias_j);
          else {
            interference[i][j][margin + bias_i].reset(margin + bias_j);
          }
        }
      }
    }
  }
  // }}}
}

bitset<20> put[40][20];
void set_put() { // {{{
  for (int i = 0; i < usable_pieces.size() * 4; i++) {
    const vector<string> a = usable_pieces[i >> 2].p[i & 0x3];
    for (int j = 0; j < puzzle_h; j++) {
      for (int k = 0; k < puzzle_w; k++) {
        if (j + a.size() > puzzle_h || k + a[0].size() > puzzle_w) {
          break;
        }

        bool f = true;
        for (int j_ = 0; j_ < a.size(); j_++) {
          for (int k_ = 0; k_ < a[j_].size(); k_++) {
            if (puzzle_flame[j + j_][k + k_] == '#' && a[j_][k_] == '#')
              f = false;
          }
        }

        if (f)
          put[i][j].set(k);
        else
          put[i][j].reset(k);
      }
    }
  }
  // cout << endl;
  // }}}
}

int piece_list;
struct position {
  int x, y;
  int n;
  position(int x_, int y_, int n_) {
    x = x_;
    y = y_;
    n = n_;
  }
};
vector<position> use;
int use_flgs;

bool solve(int y, int x) {
  /*
  cout << endl;
  for(int i = 0; i < puzzle_h; i++) {
      cout << puzzle_flame[i] << endl;
  } cout << endl;
  for(int i = 0; i < 10; i++)
      cout << (((piece_list^use_flgs) & (1 << i)) ? '1' : '0');
  cout << endl;
  for(int i = 0; i < puzzle_h; i++) {
      for(int j = 0; j < puzzle_w; j++) {
          if(puzzle_flame[i][j] == '*')
              puzzle_flame[i][j] = '#';
      }
  }
  // */
  if (!(piece_list ^ use_flgs))
    return true;
  for (int i = 0; i < puzzle_h; i++) {
    for (int j = 0; j < puzzle_w; j++) {
      if (puzzle_flame[i][j] == '.') {
        //  cout << "i,j:" << i << "," << j << endl;
        for (int k = 0; k < piece_num; k++) {
          if ((piece_list ^ use_flgs) & (1 << k)) {
            for (int l = 0; l < 4; l++) {
              int X, Y;
              Y = i - usable_pieces[k].sharp_y[l];
              X = j - usable_pieces[k].sharp_x[l];
              //          cout << X << "," << Y << "," << k << endl;
              if (Y >= 0 && X >= 0 && put[(k << 2) + l][Y][X]) {
                bool call_flg = true;
                for (int m = 0; m < use.size(); m++) {
                  call_flg &= interference[(k << 2) + l][use[m].n]
                                          [margin + use[m].y - Y]
                                          [margin + use[m].x - X];
                  //  cout << use[m].y << "," << use[m].x << "," << use[m].n <<
                  //  endl;
                }
                if (call_flg) {
                  int next_x, next_y;
                  next_x = (j + 1) % puzzle_w;
                  next_y = i + (j + 1) / puzzle_w;

                  for (int i_ = 0; i_ < usable_pieces[k].p[l].size(); i_++) {
                    for (int j_ = 0; j_ < usable_pieces[k].p[l][i_].size();
                         j_++) {
                      if (usable_pieces[k].p[l][i_][j_] == '#') {
                        /*
                        if(puzzle_flame[Y + i_][X + j_] == '#')
                            cout << "fail" << endl;
                        // */
                        puzzle_flame[Y + i_][X + j_] = '#';
                      }
                    }
                  }

                  use.push_back(position(X, Y, (k << 2) + l));
                  use_flgs |= 1 << k;

                  bool solve_res;
                  solve_res = solve(next_y, next_x);

                  for (int i_ = 0; i_ < usable_pieces[k].p[l].size(); i_++) {
                    for (int j_ = 0; j_ < usable_pieces[k].p[l][i_].size();
                         j_++) {
                      if (usable_pieces[k].p[l][i_][j_] == '#') {
                        puzzle_flame[Y + i_][X + j_] = '.';
                      }
                    }
                  }
                  use.pop_back();
                  use_flgs &= ~(1 << k);

                  if (solve_res)
                    return true;
                }
              }
            }
          }
        }

        return false;
      }
    }
  }
  return false;
}

void init_global_val() {
  puzzle_flame.clear();
  puzzle_size = 0;
  puzzle_w = 0;
  puzzle_h = 0;
  piece_num = 0;
  usable_pieces.clear();
  for (int i = 0; i < 40; i++) {
    for (int j = 0; j < 40; j++) {
      for (int k = 0; k < 64; k++) {
        for (int l = 0; l < 64; l++) {
          interference[i][j][k].set(l);
        }
      }
    }
  }
  piece_list = 0;
  use.clear();
  use_flgs = 0;
  for (int i = 0; i < 40; i++) {
    for (int j = 0; j < 20; j++) {
      for (int k = 0; k < 20; k++) {
        put[i][j].reset(k);
      }
    }
  }
}

void solve_init() {
  piece_list = 0;
  use_flgs = 0;
  use.clear();
}

int test_case = 0;
int main() {
  init_global_val();
  while (cin >> puzzle_h >> puzzle_w, puzzle_h || puzzle_w) {
    // input puzzle {{{
    if (test_case > 10)
      abort();
    test_case++;
    for (int i = 0; i < puzzle_h; i++) {
      string s;
      cin >> s;
      puzzle_flame.push_back(s);
    }
    cin >> piece_num;
    for (int i = 0; i < piece_num; i++) {
      int h, w;
      cin >> h >> w;
      vector<string> v;
      for (int j = 0; j < h; j++) {
        string s;
        cin >> s;
        v.push_back(s);
      }
      usable_pieces.push_back(piece(v));
    }
    // }}}
    // prepaire {{{
    puzzle_size = 0;
    for (int i = 0; i < puzzle_flame.size(); i++) {
      for (int j = 0; j < puzzle_flame[i].size(); j++) {
        puzzle_size += (puzzle_flame[i][j] == '.');
      }
    }

    // cout << puzzle_size << endl;

    set_interference();
    set_put();

    /*
    for(int i = 0; i < 4*usable_pieces.size(); i++) {
        cout << (i >> 2) << ":" << (i & 0x3) << endl;
        for(int j = 0; j < puzzle_h; j++) {
            for(int k = 0; k < puzzle_w; k++) {
                cout << (put[i][j][k] ? '.' : '@');
            }
            cout << endl;
        }
        cout << endl;
    }
    // */
    // }}}
    // query {{{
    int query_num;
    cin >> query_num;
    for (int q = 0; q < query_num; q++) {
      int n;
      cin >> n;
      solve_init();

      int sz = 0;
      for (int i = 0; i < n; i++) {
        int k;
        cin >> k;
        piece_list ^= (1 << (k - 1));
        sz += usable_pieces[k - 1].size;
      }

      /*
      if(puzzle_size != sz)
          cout << "size error:";
      // */
      if (puzzle_size == sz && solve(0, 0))
        cout << "YES" << endl;
      else
        cout << "NO" << endl;
    }
    // }}}
    init_global_val();
  }
}