题目大意:有一些人可以站在mxn的格子里面,有一些格子不能站人,不能站在相邻格子,有几种站法。

https://ac.nowcoder.com/acm/problem/15034

这题就是一道很基本的状态压缩DP,时间复杂度是O(m2^n2^n)对于m=n=12刚好不会TLE。
一开始没注意审题,注意支持多组数据。

ll doit(int n, int m, VI& grid) {
  int mask_size = (1 << m);
  VVL dp(n + 1, VL(mask_size, 0));
  dp[0][0] = 1;
  for (int row = 0; row < n; ++row) {
    int now = row + 1;
    int prev = row;
    for (int new_mask = 0; new_mask < mask_size; ++new_mask) {
      if (new_mask & (new_mask >> 1)) continue;
      bool fine = true;
      REP(j, m) {
        if (new_mask & (1 << j)) {
          if ((grid[row] & (1 << j)) == 0) {
            fine = false;
          }
        }
      }
      if (!fine) continue;
      for (int old_mask = 0; old_mask < mask_size; ++old_mask) {
        if (old_mask & new_mask) continue;
        dp[now][new_mask] += dp[prev][old_mask];
        dp[now][new_mask] %= MOD;
      }
    }
  }
  ll ans = 0;
  REP(i, mask_size) {
    ans += dp[n][i];
    ans %= MOD;
  }
  return ans;
}

int main(int argc, char* argv[]) {
  /* Do not use for codejam. */
  /* ios_base::sync_with_stdio(false); cin.tie(NULL); */
  int n, m;
  while (scanf("%d%d",&n,&m) == 2) {
    VI grid(n, 0);
    REP(i,n){
      REP(j,m){
        readint(curr);
        grid[i] = grid[i] * 2 + curr;
      }
    }
    printlong(doit(n,m,grid));
  }
  return 0;
}