题目大意
给你一个边长为$n$的正六边形,问有多少种用规定的Dominoes牌覆盖的方案。
简要题解
状态压缩一下每行三角形的存在状态然后DP就好。
6和7跑不过去,然而这是一道打表好题。。
年轻人不要老想着打表。
慢慢剪状态。
1:用个set存上一行可能出现的状态,而不是枚举所有可能
2:大剪枝——只有当第i行出现的三角形数量为i时的状态才是有效状态。因为前面每一行都会多出一个Dominoes牌把腿伸到后面一行来QAQ
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace my_header { 4 #define pb push_back 5 #define mp make_pair 6 #define pir pair<int, int> 7 #define vec vector<int> 8 #define pc putchar 9 #define clr(t) memset(t, 0, sizeof t) 10 #define pse(t, v) memset(t, v, sizeof t) 11 #define bl puts("") 12 #define wn(x) wr(x), bl 13 #define ws(x) wr(x), pc(' ') 14 const int INF = 0x3f3f3f3f; 15 typedef long long LL; 16 typedef double DB; 17 inline char gchar() { 18 char ret = getchar(); 19 for(; (ret == '\n' || ret == '\r' || ret == ' ') && ret != EOF; ret = getchar()); 20 return ret; } 21 template<class T> inline void fr(T &ret, char c = ' ', int flg = 1) { 22 for(c = getchar(); (c < '0' || '9' < c) && c != '-'; c = getchar()); 23 if (c == '-') { flg = -1; c = getchar(); } 24 for(ret = 0; '0' <= c && c <= '9'; c = getchar()) 25 ret = ret * 10 + c - '0'; 26 ret = ret * flg; } 27 inline int fr() { int t; fr(t); return t; } 28 template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); } 29 template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); } 30 template<class T> inline char wr(T a, int b = 10, bool p = 1) { 31 return a < 0 ? pc('-'), wr(-a, b, 0) : (a == 0 ? (p ? pc('0') : p) : 32 (wr(a/b, b, 0), pc('0' + a % b))); 33 } 34 template<class T> inline void wt(T a) { wn(a); } 35 template<class T> inline void wt(T a, T b) { ws(a), wn(b); } 36 template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); } 37 template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); } 38 template<class T> inline T gcd(T a, T b) { 39 return b == 0 ? a : gcd(b, a % b); } 40 template<class T> inline T fpw(T b, T i, T _m, T r = 1) { 41 for(; i; i >>= 1, b = b * b % _m) 42 if(i & 1) r = r * b % _m; 43 return r; } 44 }; 45 using namespace my_header; 46 47 long long f[8][1<<14]; 48 49 bool ok(int t, int w, int s, int l) { 50 for (int i = 0; i < w; ++i) { 51 if (!(t & (1 << i))) { 52 if (!(s & (1 << i))) { 53 s |= 1 << i; 54 } else if (!(s & (1 << (i + 1)))) { 55 s |= 1 << (i + 1); 56 } else { 57 return false; 58 } 59 } 60 } 61 return s == (1 << l) - 1; 62 } 63 64 set<int> S, T; 65 66 67 int main() { 68 #ifdef lol 69 freopen("D.in", "r", stdin); 70 freopen("D.out", "w", stdout); 71 #else 72 freopen("hex.in", "r", stdin); 73 freopen("hex.out", "w", stdout); 74 #endif 75 int n = fr(); 76 f[0][0] = 1; 77 S.insert(0); 78 for (int i = 1; i <= n; ++i) { 79 for (int j = 0; j < 1 << (i + n); ++j) { 80 if (__builtin_popcount(j) != i) 81 continue; 82 for (auto &&k : S) 83 if (ok(k, i + n - 1, j, i + n)) { 84 f[i][j] += f[i - 1][k]; 85 T.insert(j); 86 } 87 } 88 S.swap(T); 89 T.clear(); 90 } 91 int s = 1 << (n + n); 92 long long ans = 0; 93 for (int i = 0; i < s; ++i) { 94 //wt(f[n][i]); 95 ans += f[n][i] * f[n][i]; 96 } 97 wt(ans); 98 99 return 0; 100 }