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


#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <memory>
#include <string>

#include <algorithm>
#include <bitset>
#include <complex>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>

using namespace std;

#ifdef _MSC_VER
#define __typeof__ decltype
#define strtok_r strtok_s
#endif

#define ITER(c) __typeof__((c).begin())
#define FOREACH(it, c) for (ITER(c) it = (c).begin(); it != (c).end(); ++it)
#define RITER(c) __typeof__((c).rbegin())
#define RFOREACH(it, c) for (RITER(c) it = (c).rbegin(); it != (c).rend(); ++it)
#define REP(i, n) REPEAT(i, 0, n)
#define RREP(i, n) RREPEAT(i, 0, n)
#define REPEAT(i, k, n) for (int i = (k); i < (k + n); ++i)
#define RREPEAT(i, k, n) for (int i = (k) + (n)-1; i >= (k); --i)
#define FROMTO(i, f, t) for (int i = f; i < t; i++)
#define ALL(c) (c).begin(), (c).end()
#define LLPOW(p1, p2) ((ll)pow((double)(p1), (int)p2))
#define ESIZEOF(A) (sizeof(A) / sizeof((A)[0]))
#define CIN_NO_SYNC                                                            \\
  do {                                                                         \\
    cin.tie(0);                                                                \\
    ios_base::sync_with_stdio(false);                                          \\
  } while (0)
#define GETSTR(p) fgets((p), sizeof(p), stdin)
#define CHOMP(p)                                                               \\
  do {                                                                         \\
    char *_q = (p) + strlen(p) - 1;                                            \\
    if (*_q == '\\n' || *_q == '\\r')                                            \\
      *_q = 0;                                                                 \\
  } while (0)
#define FILL(m, v) memset(m, v, sizeof(m))
#define mp make_pair
#define pb push_back
template <class _T> _T MAX(_T p1, _T p2) { return (p1 > p2) ? p1 : p2; }
template <class _T> _T MIN(_T p1, _T p2) { return (p1 < p2) ? p1 : p2; }
template <class _Tv> inline string join(_Tv &v, string sep = " ") {
  ostringstream s;
  FOREACH(it, v) {
    if (it != v.begin())
      s << sep;
    s << *it;
  };
  return s.str();
}

typedef long long ll;
typedef unsigned long long ull;
typedef double D;
typedef complex<D> P;
#define X real()
#define Y imag()
#define EPS (1e-9)
#define DEQ(p1, p2) (abs((p1) - (p2)) < EPS)

#ifdef _DEBUG
template <class _Tv>
inline void _prfe(const char *_n, _Tv _c, bool _p = false) {
  ITER(_c) _it = _c.begin();
  if (_p) {
    cout << _n << " = [" << endl;
    for (; _it != _c.end(); ++_it)
      cout << "    " << *_it << endl;
    cout << "]" << endl;
  } else {
    cout << _n << " = [ " << *_it++;
    for (; _it != _c.end(); ++_it)
      cout << ", " << *_it;
    cout << " ]" << endl;
  }
}
#define pf printf
#define pr(n)                                                                  \\
  do {                                                                         \\
    cout << #n " = " << (n) << endl;                                           \\
  } while (0)
#define prfe(n) _prfe(#n, n)
#define prfep(n) _prfe(#n, n, true)
#define dbgchk(n)                                                              \\
  do {                                                                         \\
    if (n)                                                                     \\
      throw;                                                                   \\
  } while (0)
#else
#define pf(...)     /* */
#define pr(...)     /* */
#define prfe(...)   /* */
#define prfep(...)  /* */
#define dbgchk(...) /* */
#endif

inline void bitset(ull &p, int n) { p |= (1ULL << n); }
inline void bitunset(ull &p, int n) { p &= ~(1ULL << n); }
inline bool bitisset(ull p, int n) { return !!(p & (1ULL << n)); };
inline int bitcount(ull p) {
  int c = 0;
  for (; p; p &= p - 1)
    c++;
  return c;
}

class MAPDATA {
public:
  int w, h;
  unsigned int v[20];
  bool operator<(const MAPDATA &m) const {
    REP(i, 20) {
      if (v[i] != m.v[i])
        return v[i] < m.v[i];
    }
    return false;
  }
  bool check(int cx, int cy, const MAPDATA &m) const {
    if (cx < 0 || cy < 0)
      return false;
    if (cx + m.w > w || cy + m.h > h)
      return false;
    REP(y, m.h) {
      unsigned int n1 = v[cy + y];
      unsigned int n2 = m.v[y] >> cx;
      if ((n1 & n2) != 0)
        return false;
    }
    return true;
  }
  bool set(int cx, int cy, const MAPDATA &m) {
    if (cx < 0 || cy < 0)
      return false;
    if (cx + m.w > w || cy + m.h > h)
      return false;
    REP(y, m.h) { v[cy + y] |= (m.v[y] >> cx); }
    return true;
  }
  bool isfilled(void) {
    unsigned int tv = -1;
    REP(y, h) tv &= v[y];
    return ((tv >> (32 - w)) == (1 << w) - 1);
  }

  void prmap() const {
#ifdef _DEBUG
    printf("-- (%d,%d) --\\n", w, h);
    REP(y, h) {
      unsigned int n = v[y];
      REP(x, w) {
        if (n & (1 << 31)) {
          printf("#");
        } else {
          printf(" ");
        }
        n <<= 1;
      }
      printf("\\n");
    }
#endif
  }
};

int vpn;
MAPDATA vp[40];
vector<int> vpc;
vector<int> vpw, vph, vpbx, vpby;
int vtn;
vector<int> vt;

set<MAPDATA> memo[10];

bool dfs(const MAPDATA &m, int n, int mc) {
  int mw = m.w, mh = m.h;
  int mbx = -1, mby = -1;

  if (n == vtn)
    return true;

  if (memo[n].find(m) != memo[n].end())
    return false;
  memo[n].insert(m);

  REP(y, mh) {
    unsigned int n = m.v[y];
    if (~n == 0)
      continue;
    REP(x, mw) {
      if (!(n & (1 << 31))) {
        mbx = x, mby = y;
        break;
      }
      n <<= 1;
    }
    if (mby >= 0)
      break;
  }

  m.prmap();
  pf("mb = (%d,%d)\\n", mbx, mby);

  MAPDATA fill = m;
  FROMTO(i, n, vtn) REP(r, 4) {
    int pi = vt[i] + vpn * r;
    MAPDATA &vpr = vp[pi];
    int cx = mw - vpr.w + 1;
    int cy = mh - vpr.h + 1;
    vpr.prmap();
    FROMTO(y, mby, cy) {
      REP(x, cx) {
        if (m.check(x, y, vpr)) {
          fill.set(x, y, vpr);
        }
      }
    }
  }
  if (!fill.isfilled()) {
    fill.prmap();
    return false;
  }

  REP(r, 4) {
    int pi = vt[n] + vpn * r;
    MAPDATA &vpr = vp[pi];
    int cx = mw - vpr.w + 1;
    int cy = mh - vpr.h + 1;
    FROMTO(y, mby, cy) {
      REP(x, cx) {
        if (m.check(x, y, vpr)) {
          MAPDATA m0 = m;
          m0.set(x, y, vpr);
          if (dfs(m0, n + 1, mc - vpc[vt[n]]))
            return true;
        }
      }
    }
  }
  return false;
}

bool rotate(const vector<string> &a, vector<string> &b, int r) {
  int w = a[0].size();
  int h = a.size();
  if (r == 0) {
    b = a;
    return true;
  }
  if (r == 2) {
    b = a;
    reverse(ALL(b));
    FOREACH(it, b) reverse(ALL(*it));
  }
  if (r == 1) {
    b.resize(w);
    REP(i, w) b[i].resize(h);
    REP(y, h) REP(x, w) b[x][h - y - 1] = a[y][x];
  }
  if (r == 3) {
    b.resize(w);
    REP(i, w) b[i].resize(h);
    REP(y, h) REP(x, w) b[w - x - 1][y] = a[y][x];
  }
  // pf("---- %d ----\\n", r);
  // prfep(b);
  if ((int)b[0].size() != w || (int)b.size() != h)
    return true;
  REP(y, h) REP(x, w) {
    if (a[y][x] != b[y][x])
      return true;
  }
  return false;
}

int ps(const MAPDATA &m) {
  int c = 0;
  REP(i, m.h) c += bitcount(m.v[i] >> (32 - m.w));
  return c;
}

string solve(const MAPDATA &m) {
  int mc = m.h * m.w - ps(m);
  int pc = 0;
  FOREACH(it, vt) pc += ps(vp[*it]);
  pf("mc = %d, pc = %d\\n", mc, pc);
  if (mc != pc)
    return "NO";

  REP(i, 10) memo[i].clear();
  return dfs(m, 0, mc) ? "YES" : "NO";
}

void getbase(const vector<string> &vp, int &vpw, int &vph, int &vpbx,
             int &vpby) {
  vpw = vp[0].size();
  vph = vp.size();
  REP(y, vph) REP(x, vpw) {
    if (vp[y][x] == '#') {
      vpbx = x, vpby = y;
      pf("vpw = %d, vph = %d, vpbx = %d, vpby = %d\\n", vpw, vph, vpbx, vpby);
      return;
    }
  }
}
void normalize(vector<string> &vp) {
  int w = vp[0].size(), h = vp.size();
  int x1 = w, y1 = h, x2 = 0, y2 = 0;
  REP(y, h) REP(x, w) {
    if (vp[y][x] == '#') {
      x1 = min(x1, x);
      y1 = min(y1, y);
      x2 = max(x2, x + 1);
      y2 = max(y2, y + 1);
    }
  }
  if (x1 == 0 && y1 == 0 && x2 == w && y2 == h)
    return;
  if (x2 < x1 || y2 < y1)
    throw;

  w = x2 - x1, h = y2 - y1;
  vector<string> t(h);
  REP(y, h) {
    t[y].resize(w);
    REP(x, w) t[y][x] = vp[y1 + y][x1 + x];
  }
  vp = t;
}

void v2m(int w, int h, vector<string> &v, MAPDATA &m) {
  REP(y, h) {
    REP(x, w) {
      m.v[y] <<= 1;
      if (v[y][x] == '#') {
        m.v[y] |= 1;
      }
    }
    m.v[y] <<= (32 - w);
  }
  m.w = w;
  m.h = h;
}

int main() {

  int w, h;
  while (cin >> h >> w) {
    if (h == 0 && w == 0)
      break;
    vector<string> v(h);
    REP(i, h) cin >> v[i];

    MAPDATA m;
    v2m(w, h, v, m);
    m.prmap();

    int n;
    cin >> n;
    vpn = n;
    vpc.resize(n);
    vpw.resize(n * 4);
    vph.resize(n * 4);
    vpbx.resize(n * 4);
    vpby.resize(n * 4);
    REP(i, n) {
      int w1, h1;
      cin >> h1 >> w1;
      vector<string> v(h1);
      REP(j, h1) cin >> v[j];
      normalize(v);

      REP(j, 4) {
        vector<string> v2(h1);
        rotate(v, v2, j);
        getbase(v2, vpw[i + j * n], vph[i + j * n], vpbx[i + j * n],
                vpby[i + j * n]);
        v2m(vpw[i + j * n], vph[i + j * n], v2, vp[i + j * n]);
        vp[i + j * n].prmap();
      }
      vpc[i] = ps(vp[i]);
    }

    int p;
    cin >> p;
    REP(i, p) {
      int k, t;
      cin >> k;
      vt.resize(k);
      vtn = k;
      REP(j, k) {
        cin >> t;
        vt[j] = t - 1;
      }
      RREP(j, k) {
        REP(l, j) {
          if (vpc[vt[l]] < vpc[vt[l + 1]]) {
            swap(vt[l], vt[l + 1]);
          }
        }
      }
      cout << solve(m) << endl;
      // int cnt = 0; REP(i,10) cnt += memo[i].size(); printf("cnt = %d\\n",
      // cnt);
    }
  }
  return 0;
}

Error: MLE

Fixed submission:


#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <memory>
#include <string>

#include <algorithm>
#include <bitset>
#include <complex>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>

using namespace std;

#ifdef _MSC_VER
#define __typeof__ decltype
#define strtok_r strtok_s
#endif

#define ITER(c) __typeof__((c).begin())
#define FOREACH(it, c) for (ITER(c) it = (c).begin(); it != (c).end(); ++it)
#define RITER(c) __typeof__((c).rbegin())
#define RFOREACH(it, c) for (RITER(c) it = (c).rbegin(); it != (c).rend(); ++it)
#define REP(i, n) REPEAT(i, 0, n)
#define RREP(i, n) RREPEAT(i, 0, n)
#define REPEAT(i, k, n) for (int i = (k); i < (k + n); ++i)
#define RREPEAT(i, k, n) for (int i = (k) + (n)-1; i >= (k); --i)
#define FROMTO(i, f, t) for (int i = f; i < t; i++)
#define ALL(c) (c).begin(), (c).end()
#define LLPOW(p1, p2) ((ll)pow((double)(p1), (int)p2))
#define ESIZEOF(A) (sizeof(A) / sizeof((A)[0]))
#define CIN_NO_SYNC                                                            \\
  do {                                                                         \\
    cin.tie(0);                                                                \\
    ios_base::sync_with_stdio(false);                                          \\
  } while (0)
#define GETSTR(p) fgets((p), sizeof(p), stdin)
#define CHOMP(p)                                                               \\
  do {                                                                         \\
    char *_q = (p) + strlen(p) - 1;                                            \\
    if (*_q == '\\n' || *_q == '\\r')                                            \\
      *_q = 0;                                                                 \\
  } while (0)
#define FILL(m, v) memset(m, v, sizeof(m))
#define mp make_pair
#define pb push_back
template <class _T> _T MAX(_T p1, _T p2) { return (p1 > p2) ? p1 : p2; }
template <class _T> _T MIN(_T p1, _T p2) { return (p1 < p2) ? p1 : p2; }
template <class _Tv> inline string join(_Tv &v, string sep = " ") {
  ostringstream s;
  FOREACH(it, v) {
    if (it != v.begin())
      s << sep;
    s << *it;
  };
  return s.str();
}

typedef long long ll;
typedef unsigned long long ull;
typedef double D;
typedef complex<D> P;
#define X real()
#define Y imag()
#define EPS (1e-9)
#define DEQ(p1, p2) (abs((p1) - (p2)) < EPS)

#ifdef _DEBUG
template <class _Tv>
inline void _prfe(const char *_n, _Tv _c, bool _p = false) {
  ITER(_c) _it = _c.begin();
  if (_p) {
    cout << _n << " = [" << endl;
    for (; _it != _c.end(); ++_it)
      cout << "    " << *_it << endl;
    cout << "]" << endl;
  } else {
    cout << _n << " = [ " << *_it++;
    for (; _it != _c.end(); ++_it)
      cout << ", " << *_it;
    cout << " ]" << endl;
  }
}
#define pf printf
#define pr(n)                                                                  \\
  do {                                                                         \\
    cout << #n " = " << (n) << endl;                                           \\
  } while (0)
#define prfe(n) _prfe(#n, n)
#define prfep(n) _prfe(#n, n, true)
#define dbgchk(n)                                                              \\
  do {                                                                         \\
    if (n)                                                                     \\
      throw;                                                                   \\
  } while (0)
#else
#define pf(...)     /* */
#define pr(...)     /* */
#define prfe(...)   /* */
#define prfep(...)  /* */
#define dbgchk(...) /* */
#endif

inline void bitset(ull &p, int n) { p |= (1ULL << n); }
inline void bitunset(ull &p, int n) { p &= ~(1ULL << n); }
inline bool bitisset(ull p, int n) { return !!(p & (1ULL << n)); };
inline int bitcount(ull p) {
  int c = 0;
  for (; p; p &= p - 1)
    c++;
  return c;
}

class MAPDATA {
public:
  int w, h;
  unsigned int v[20];
  bool operator<(const MAPDATA &m) const {
    REP(i, 20) {
      if (v[i] != m.v[i])
        return v[i] < m.v[i];
    }
    return false;
  }
  bool check(int cx, int cy, const MAPDATA &m) const {
    if (cx < 0 || cy < 0)
      return false;
    if (cx + m.w > w || cy + m.h > h)
      return false;
    REP(y, m.h) {
      unsigned int n1 = v[cy + y];
      unsigned int n2 = m.v[y] >> cx;
      if ((n1 & n2) != 0)
        return false;
    }
    return true;
  }
  bool set(int cx, int cy, const MAPDATA &m) {
    if (cx < 0 || cy < 0)
      return false;
    if (cx + m.w > w || cy + m.h > h)
      return false;
    REP(y, m.h) { v[cy + y] |= (m.v[y] >> cx); }
    return true;
  }

  void prmap() const {
#ifdef _DEBUG
    printf("-- (%d,%d) --\\n", w, h);
    REP(y, h) {
      unsigned int n = v[y];
      REP(x, w) {
        if (n & (1 << 31)) {
          printf("#");
        } else {
          printf(" ");
        }
        n <<= 1;
      }
      printf("\\n");
    }
#endif
  }
};

int vpn;
MAPDATA vp[40];
vector<int> vpc;
vector<int> vpw, vph, vpbx, vpby;
int vtn;
vector<int> vt;

set<MAPDATA> memo[10];

bool dfs(const MAPDATA &m, int n, int mc) {
  int mw = m.w, mh = m.h;
  int mbx = -1, mby = -1;

  if (n == vtn)
    return true;

  if (memo[n].find(m) != memo[n].end())
    return false;
  memo[n].insert(m);

  REP(y, mh) {
    unsigned int n = m.v[y];
    if (~n == 0)
      continue;
    REP(x, mw) {
      if (!(n & (1 << 31))) {
        mbx = x, mby = y;
        break;
      }
      n <<= 1;
    }
    if (mby >= 0)
      break;
  }

  m.prmap();
  pf("mb = (%d,%d)\\n", mbx, mby);

  bool flag = false;
  FROMTO(i, n, vtn) {
    REP(r, 4) {
      int pi = vt[i] + vpn * r;
      MAPDATA &vpr = vp[pi];
      int cx = mbx - vpbx[pi];
      int cy = mby - vpby[pi];
      if (m.check(cx, cy, vpr)) {
        vpr.prmap();
        flag = true;
        break;
      }
    }
    if (flag)
      break;
  }
  if (!flag) {
    return false;
  }

  REP(r, 4) {
    int pi = vt[n] + vpn * r;
    MAPDATA &vpr = vp[pi];
    int cx = mw - vpr.w + 1;
    int cy = mh - vpr.h + 1;
    FROMTO(y, mby, cy) {
      REP(x, cx) {
        if (m.check(x, y, vpr)) {
          MAPDATA m0 = m;
          m0.set(x, y, vpr);
          if (dfs(m0, n + 1, mc - vpc[vt[n]]))
            return true;
        }
      }
    }
  }
  return false;
}

bool rotate(const vector<string> &a, vector<string> &b, int r) {
  int w = a[0].size();
  int h = a.size();
  if (r == 0) {
    b = a;
    return true;
  }
  if (r == 2) {
    b = a;
    reverse(ALL(b));
    FOREACH(it, b) reverse(ALL(*it));
  }
  if (r == 1) {
    b.resize(w);
    REP(i, w) b[i].resize(h);
    REP(y, h) REP(x, w) b[x][h - y - 1] = a[y][x];
  }
  if (r == 3) {
    b.resize(w);
    REP(i, w) b[i].resize(h);
    REP(y, h) REP(x, w) b[w - x - 1][y] = a[y][x];
  }
  // pf("---- %d ----\\n", r);
  // prfep(b);
  if ((int)b[0].size() != w || (int)b.size() != h)
    return true;
  REP(y, h) REP(x, w) {
    if (a[y][x] != b[y][x])
      return true;
  }
  return false;
}

int ps(const MAPDATA &m) {
  int c = 0;
  REP(i, m.h) c += bitcount(m.v[i] >> (32 - m.w));
  return c;
}

string solve(const MAPDATA &m) {
  int mc = m.h * m.w - ps(m);
  int pc = 0;
  FOREACH(it, vt) pc += ps(vp[*it]);
  pf("mc = %d, pc = %d\\n", mc, pc);
  if (mc != pc)
    return "NO";

  REP(i, 10) memo[i].clear();
  return dfs(m, 0, mc) ? "YES" : "NO";
}

void getbase(const vector<string> &vp, int &vpw, int &vph, int &vpbx,
             int &vpby) {
  vpw = vp[0].size();
  vph = vp.size();
  REP(y, vph) REP(x, vpw) {
    if (vp[y][x] == '#') {
      vpbx = x, vpby = y;
      pf("vpw = %d, vph = %d, vpbx = %d, vpby = %d\\n", vpw, vph, vpbx, vpby);
      return;
    }
  }
}
void normalize(vector<string> &vp) {
  int w = vp[0].size(), h = vp.size();
  int x1 = w, y1 = h, x2 = 0, y2 = 0;
  REP(y, h) REP(x, w) {
    if (vp[y][x] == '#') {
      x1 = min(x1, x);
      y1 = min(y1, y);
      x2 = max(x2, x + 1);
      y2 = max(y2, y + 1);
    }
  }
  if (x1 == 0 && y1 == 0 && x2 == w && y2 == h)
    return;
  if (x2 < x1 || y2 < y1)
    throw;

  w = x2 - x1, h = y2 - y1;
  vector<string> t(h);
  REP(y, h) {
    t[y].resize(w);
    REP(x, w) t[y][x] = vp[y1 + y][x1 + x];
  }
  vp = t;
}

void v2m(int w, int h, vector<string> &v, MAPDATA &m) {
  REP(y, h) {
    REP(x, w) {
      m.v[y] <<= 1;
      if (v[y][x] == '#') {
        m.v[y] |= 1;
      }
    }
    m.v[y] <<= (32 - w);
  }
  m.w = w;
  m.h = h;
}

int main() {

  int w, h;
  while (cin >> h >> w) {
    if (h == 0 && w == 0)
      break;
    vector<string> v(h);
    REP(i, h) cin >> v[i];

    MAPDATA m;
    v2m(w, h, v, m);
    m.prmap();

    int n;
    cin >> n;
    vpn = n;
    vpc.resize(n);
    vpw.resize(n * 4);
    vph.resize(n * 4);
    vpbx.resize(n * 4);
    vpby.resize(n * 4);
    REP(i, n) {
      int w1, h1;
      cin >> h1 >> w1;
      vector<string> v(h1);
      REP(j, h1) cin >> v[j];
      normalize(v);

      REP(j, 4) {
        vector<string> v2(h1);
        rotate(v, v2, j);
        getbase(v2, vpw[i + j * n], vph[i + j * n], vpbx[i + j * n],
                vpby[i + j * n]);
        v2m(vpw[i + j * n], vph[i + j * n], v2, vp[i + j * n]);
        vp[i + j * n].prmap();
      }
      vpc[i] = ps(vp[i]);
    }

    int p;
    cin >> p;
    REP(i, p) {
      int k, t;
      cin >> k;
      vt.resize(k);
      vtn = k;
      REP(j, k) {
        cin >> t;
        vt[j] = t - 1;
      }
      RREP(j, k) {
        REP(l, j) {
          if (vpc[vt[l]] < vpc[vt[l + 1]]) {
            swap(vt[l], vt[l + 1]);
          }
        }
      }
      cout << solve(m) << endl;
    }
  }
  return 0;
}