メモ化する。
memo[BIT]で挑むとTLE喰らう。memo[C][R][BIT]にしよう。
テストデータが意地悪すぎる。何か面倒だった。
- #include <iostream>
- #include <algorithm>
- #include <vector>
- #include <set>
- #include <map>
- #include <queue>
- #include <stack>
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <cmath>
- #define REP(i, n) for(int i=0; i<(int)n; ++i)
- #define FOR(i, c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
- #define ALL(c) (c).begin(),(c).end()
- typedef long long int lli;
- using namespace std;
- const int R = 4;
- const int C = 4;
- const int BIT = (1 << (C * R + 1));
- int memo[C][R][BIT];
- int no(int c, int r, int i, int j)
- {
- return r * i + j;
- }
- int rec(int bit, int c, int r)
- {
- if (memo[c - 1][r -1][bit] != -1) return memo[c - 1][r - 1][bit];
- if (__builtin_popcount(bit) == 1) return memo[c - 1][r - 1][bit] = 1;
- int sum = 0;
- int di[] = {-1, -1, -1, 0, 0, 1, 1, 1};
- int dj[] = {-1, 0, 1, -1, 1, -1, 0, 1};
- for (int i = 0; i < c; ++i) {
- for (int j = 0; j < r; ++j) {
- if (bit & (1 << no(c, r, i, j))) ; else continue;
- for (int d = 0; d < 8; ++d) {
- int ni = i + di[d];
- int nj = j + dj[d];
- int mi = i + di[d] * 2;
- int mj = j + dj[d] * 2;
- if (mi < 0 || mj < 0) continue;
- if (c <= mi || r <= mj) continue;
- if (bit & (1 << no(c, r, ni, nj))) ; else continue;
- if (bit & (1 << no(c, r, mi, mj))) continue;
- int next = bit;
- next ^= 1 << no(c, r, i, j);
- next ^= 1 << no(c, r, ni, nj);
- next ^= 1 << no(c, r, mi, mj);
- sum += rec(next, c, r);
- }
- }
- }
- return memo[c - 1][r - 1][bit] = sum;
- }
- int main(int argc, char *argv[])
- {
- fill(&memo[0][0][0], &memo[C - 1][R - 1][BIT], -1);
- int tc;
- scanf("%d\n", &tc);
- while (tc--) {
- int r, c, n;
- int bit = 0;
- scanf("%d %d %d\n", &r, &c, &n);
- while (n--) {
- int i, j;
- scanf("%d %d\n", &j, &i);
- --i;
- --j;
- bit |= 1 << no(c, r, i, j);
- }
- static int cnt = 0;
- printf("Case %d: %d\n", ++cnt, rec(bit, c, r));
- }
- return 0;
- }
0 件のコメント :
コメントを投稿