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

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <queue>
#include <set>
#include <vector>

using namespace std;

static const int di[] = {-1, 0, 1, 0};
static const int dj[] = {0, 1, 0, -1};

typedef pair<int, int> pi;

#define MAX 16
#define fr first
#define sc second
#define MAXDIR 4

// vector<pi> houses;
int houseId[MAX][MAX];
pi charch;

struct Node {
  bool isCharch;
  bool isHouse;
  int linkmax[MAXDIR];
  pi link[MAXDIR][MAX];
  bool exist[MAXDIR];
  bool cexist[MAXDIR];
  Node() : isCharch(false), isHouse(false) {
    for (int i = 0; i < MAXDIR; ++i) {
      linkmax[i] = 0;
      cexist[i] = exist[i] = false;
    }
  }
};

struct state {
  char ni, nj;
  char cnt;
  int vis;
  state() {}
  state(char si, char sj, char cnt, int vis)
      : ni(si), nj(sj), cnt(cnt), vis(vis) {}
};

// void bfs(Node M[][MAX], state init, int nhouse, int &ans);

inline bool isinside(int H, int W, int i, int j) {
  return 0 <= i && i < H && 0 <= j && j < W;
}

class Queue {
private:
  int p;
  state *V;

public:
  Queue() : p(0) { V = new state[1 << 20]; }
  ~Queue() { delete[] V; }
  void push(const state &t) { V[p++] = t; }
  state *front() { return &V[p - 1]; }
  void pop() { --p; }
  bool empty() { return p == 0; }
};

void bfs(const Node M[][MAX], state init, int nhouse, int &ans) {
  Queue qs;
  qs.push(init);
  int ni, nj;
  int housenum = 0;
  int chi = charch.fr;
  int chj = charch.sc;

  for (int k = 0; k < MAXDIR; ++k) {
    housenum += M[chi][chj].linkmax[k];
  }

  while (!qs.empty()) {
    state st_now = *(qs.front());
    ni = st_now.ni;
    nj = st_now.nj;
    qs.pop();

    if (st_now.cnt == nhouse) {
      for (int l = 0; l < MAXDIR; ++l) {
        if (M[ni][nj].cexist[l]) {
          ++ans;
          break;
        }
      }
      continue;
    } else {

      int left = housenum;
      for (int k = 0; k < MAXDIR; ++k) {
        for (int v = 0; v < M[chi][chj].linkmax[k]; ++v) {
          pi hs = M[chi][chj].link[k][v];
          left -= (bool)(st_now.vis & (1 << houseId[hs.fr][hs.sc]));
        }
      }
      if (left == 0)
        continue;

      for (int k = 0; k < MAXDIR; ++k) {
        for (int v = 0; v < M[ni][nj].linkmax[k]; ++v) {
          pi next = M[ni][nj].link[k][v];
          int mask = 1 << houseId[next.fr][next.sc];
          if (!(st_now.vis & mask)) {
            qs.push(state(next.fr, next.sc, st_now.cnt + 1, st_now.vis | mask));
            break;
          }
        }
      }
    }
  }
  return;
}

int main() {
  while (true) {
    int ans = 0;
    int W, H;
    scanf("%d%d", &W, &H);
    if (W == 0 && W == H)
      break;
    int iM[MAX][MAX];
    Node M[MAX][MAX];

    int nhouse = 0;

    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        scanf("%d", &iM[i][j]);
        if (iM[i][j] == 1) {
          ++nhouse;
          houseId[i][j] = nhouse;
          M[i][j].isHouse = true;
        } else if (iM[i][j] == 2) {
          M[i][j].isCharch = true;
          charch = pi(i, j);
        }
      }
    }

    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        for (int k = 0; k < MAXDIR; ++k) {
          int ti = i + di[k];
          int tj = j + dj[k];
          while (isinside(H, W, ti, tj)) {
            if (M[ti][tj].isHouse) {
              M[i][j].link[k][M[i][j].linkmax[k]++] = pi(ti, tj);
              M[i][j].exist[k] = true;
            } else if (M[ti][tj].isCharch) {
              M[i][j].cexist[k] = true;
            }
            ti += di[k];
            tj += dj[k];
          }
        }
      }
    }

    state init(charch.fr, charch.sc, 0, 0);
    bfs(M, init, nhouse, ans);
    printf("%d\\n", ans);
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <queue>
#include <set>
#include <vector>

using namespace std;

static const int di[] = {-1, 0, 1, 0};
static const int dj[] = {0, 1, 0, -1};

typedef pair<int, int> pi;

#define MAX 16
#define fr first
#define sc second
#define MAXDIR 4

// vector<pi> houses;
int houseId[MAX][MAX];
pi charch;

struct Node {
  bool isCharch;
  bool isHouse;
  int linkmax[MAXDIR];
  pi link[MAXDIR][MAX];
  bool exist[MAXDIR];
  bool cexist[MAXDIR];
  Node() : isCharch(false), isHouse(false) {
    for (int i = 0; i < MAXDIR; ++i) {
      linkmax[i] = 0;
      cexist[i] = exist[i] = false;
    }
  }
};

struct state {
  char ni, nj;
  char cnt;
  int vis;
  state() {}
  state(char si, char sj, char cnt, int vis)
      : ni(si), nj(sj), cnt(cnt), vis(vis) {}
};

// void bfs(Node M[][MAX], state init, int nhouse, int &ans);

inline bool isinside(int H, int W, int i, int j) {
  return 0 <= i && i < H && 0 <= j && j < W;
}

struct Queue {
  int p;
  state *V;
  Queue() : p(0) { V = new state[1 << 20]; }
  ~Queue() { delete[] V; }
  void push(const state &t) { V[p++] = t; }
  state *front() { return &V[p - 1]; }
  void pop() { --p; }
  bool empty() { return p == 0; }
};

void bfs(const Node M[][MAX], state init, int nhouse, int &ans) {
  Queue qs;
  qs.push(init);
  int ni, nj;
  int housenum = 0;
  int chi = charch.fr;
  int chj = charch.sc;

  for (int k = 0; k < MAXDIR; ++k) {
    housenum += M[chi][chj].linkmax[k];
  }

  while (!qs.empty()) {
    state st_now = *(qs.front());
    ni = st_now.ni;
    nj = st_now.nj;
    qs.pop();

    if (st_now.cnt == nhouse) {
      for (int l = 0; l < MAXDIR; ++l) {
        if (M[ni][nj].cexist[l]) {
          ++ans;
          break;
        }
      }
      continue;
    } else {

      int left = housenum;
      for (int k = 0; k < MAXDIR; ++k) {
        for (int v = 0; v < M[chi][chj].linkmax[k]; ++v) {
          pi hs = M[chi][chj].link[k][v];
          if (st_now.vis & (1 << houseId[hs.fr][hs.sc])) {
            --left;
          }
        }
      }
      if (left == 0)
        continue;

      for (int k = 0; k < MAXDIR; ++k) {
        for (int v = 0; v < M[ni][nj].linkmax[k]; ++v) {
          pi next = M[ni][nj].link[k][v];
          int mask = 1 << houseId[next.fr][next.sc];
          if (!(st_now.vis & mask)) {
            qs.push(state(next.fr, next.sc, st_now.cnt + 1, st_now.vis | mask));
            break;
          }
        }
      }
    }
  }
  return;
}

int main() {
  while (true) {
    int ans = 0;
    int W, H;
    scanf("%d%d", &W, &H);
    if (W == 0 && W == H)
      break;
    int iM[MAX][MAX];
    Node M[MAX][MAX];

    int nhouse = 0;

    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        scanf("%d", &iM[i][j]);
        if (iM[i][j] == 1) {
          ++nhouse;
          houseId[i][j] = nhouse;
          M[i][j].isHouse = true;
        } else if (iM[i][j] == 2) {
          M[i][j].isCharch = true;
          charch = pi(i, j);
        }
      }
    }

    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        for (int k = 0; k < MAXDIR; ++k) {
          int ti = i + di[k];
          int tj = j + dj[k];
          while (isinside(H, W, ti, tj)) {
            if (M[ti][tj].isHouse) {
              M[i][j].link[k][M[i][j].linkmax[k]++] = pi(ti, tj);
              M[i][j].exist[k] = true;
            } else if (M[ti][tj].isCharch) {
              M[i][j].cexist[k] = true;
            }
            ti += di[k];
            tj += dj[k];
          }
        }
      }
    }

    state init(charch.fr, charch.sc, 0, 0);
    bfs(M, init, nhouse, ans);
    printf("%d\\n", ans);
  }
  return 0;
}