/* What a TROUBLESOME Problem!!! Obviously, we should construct a sparse table which has 60 * 63 rows and 60 + 12 colums. 60 * 63 rows 60 means we can place the "center" of a block on a specific grid. Besides, as block can be rotated or fliped, we can regard the transformed-block as a distinct block. So we get 63 distinct blocks. The classification above can avoid most of duplicate answers. (About the "center": Imagine that each block's original form can be place in a 3 * 5 matrix, then intuitively, (2, 2) will be the center lol) 60 + 12 colums 60 colums indicate 60 grids 12 colums indicate that each block can be used at most one time. Then dance!!! As 60 only has 6 factor thus I can work out all the answers in advance and I must do, otherwise, I would get a TLE by using my DLX. At last, all the answers should be divided by 4, because it includes some duplicate results which is a rotating or flipping of another results. HINTS about rotating & flipping: If a block is axisymmetry or centrosymmetry, it can only generate 3 more blocks. If a block is axisymmetry and centrosymmetry, originnal form is the only state. Why? Generally, we can get all 7 generated blocks in total by rotate the original block 3 times clockwisely and flip it, then rotate it 3 times clockwisely. As a axisymmetry block's flipping-rotating-status are included in rotating-status, and centrosymmery block can return to originnal form by rotate 180 degree, the block which has one of these characteristics can only generate 3 more distinct blocks. Last but not least, clear your mind and thanks to read my suck english-expression. */ #if 1 //Header #include <cstdio> #include <cstdlib> #include <iostream> #include <cstring> #include <string> #include <vector> #include <map> #include <algorithm> #include <cctype> #include <queue> #include <stack> #include <cmath> using namespace std; #endif #if 1 //Macro //STL-Alias #define UN(c, a) unique(c, a) #define MS(c, a) memset(c, a, sizeof c) #define FLC(c, a ,b) fill(c, c + a, b) #define LOS(c, a, b) lower_bound(c, a, b) #define UPS(c, a, b) upper_bound(c, a, b) //Syntax-Alias #define Rep(c, a, b) for (int c = (a); c < (b); c++) #define Nre(c, a, b) for (int c = (a); c > (b); c--) //DEBUG #define FK puts("Fu*k here!") #define PA(s, c, a, b, p, f){\ printf(s);\ Rep(c, a, b) printf(p, (f));\ puts("");} //Constant #define INFI (0x7fffffff) #define MOD () #define MAXN (66) #define MAXT (12) //Type-Alias typedef long long LL; typedef long double LD; typedef int AI[MAXN]; typedef bool AB[MAXN]; typedef double AD[MAXN]; typedef LL ALL[MAXN]; typedef LD ALD[MAXN]; #endif //DLX struct DLX { #define DLXR (MAXN * MAXT * 8) #define DLXC (MAXT + MAXN) #define DF(c, a, b) for (int c = a[b]; c != b; c = a[c]) typedef int DS[DLXR * DLXC], DR[DLXR], DC[DLXC]; DS L, R, U, D, O, C; DR P; DC S; vector<vector<int> > ans; int id, cr, rh, ms, res; void ini(int n) { id = ++n; Rep(i, 0, n) { L[i] = (i - 1 + n) % n; R[i] = (i + 1) % n; U[i] = D[i] = i; } MS(S, cr = 0); MS(P, 0); ms = INFI; res = 0; ans.clear(); } void ins(int i, int j) { i++; j++; if (cr < i) { rh = L[id] = R[id] = id; cr = i; } L[id] = L[rh]; R[id] = rh; R[L[rh]] = id; L[rh] = id; U[id] = U[j]; D[id] = j; D[U[j]] = id; U[j] = id; S[j]++; O[id] = i; C[id++] = j; } void erm(int c) { L[R[c]] = L[c]; R[L[c]] = R[c]; DF(i, D, c) DF(j, R, i) U[D[j]] = U[j], D[U[j]] = D[j], S[C[j]]--; } void ers(int c) { L[R[c]] = c; R[L[c]] = c; DF(i, D, c) DF(j, R, i) U[D[j]] = j, D[U[j]] = j, S[C[j]]++; } bool edf(int sp) { if (!R[0] || R[0] >= ms) { res++; return 1; } int x = R[0]; DF(i, R, 0) if (i < ms && S[i] < S[x]) x = i; erm(x); DF(i, D, x) { DF(j, R, i) erm(C[j]); edf(sp + 1); DF(j, L, i) ers(C[j]); //L } ers(x); return 0; } } dlx; #if 1 //Tiles #if 1 //Direction #define O (0 ) #define E (1 ) #define S (2 ) #define W (3 ) #define N (4 ) #define SE (5 ) #define SW (6 ) #define NW (7 ) #define NE (8 ) #define EE (9 ) #define WW (10) // NW N NE //WW W O E EE // SW S SE #endif int dir[11][2] = { {0, 0},//O {0, 1}, {1, 0}, { 0, -1}, {-1, 0},//E , S, W, N {1, 1}, {1, -1}, {-1, -1}, {-1, 1},//SE, SW, NW, NE {0, 2}, {0, -2}//EE, WW }; int til[MAXT][5] = { {SE, S, SW, W, NW},//1 { O, E, EE, W, WW},//2 { O, E, S, W, N},//3 { E, SE, S, SW, W},//4 { O, E, EE, W, NW},//5 { O, SE, S, W, NW},//6 { O, E, EE, W, N},//7 { O, E, SW, W, NE},//8 { O, E, S, SW, N},//9 { O, SE, S, SW, N},//10 { O, E, SE, S, SW},//11 { O, E, EE, S, SW},//12 }; int otm[MAXT + 1] = {4, 2, 1, 4, 8, 4, 8, 8, 8, 4, 8, 8, 67}; //otm[i] = (Flip or not) * 4 + Rotate-times. int sot[MAXT] = {0, 4, 6, 7, 11, 19, 23, 31, 39, 47, 51, 59}; //sum of otm[i] which i in [0, i - 1]. void flp(int &x, int &y, int f) //Flipping { if (f) x = -x; } void rot(int &x, int &y, int b) //Rotation { while (b--) { swap(x, y); y = -y; } } #endif int n, m; vector<int> P; bool CAI(int x, int y, int t, int f, int b) //Check and Insert { P.clear(); Rep(i, 0, 5) { int p = dir[til[t][i]][0], q = dir[til[t][i]][1]; flp(p, q, f); rot(p, q, b); int tx = x + p, ty = y + q; if (tx < 0 || n <= tx || ty < 0 || m <= ty) return 0; else P.push_back(tx * m + ty); } int u = (x * m + y) * otm[MAXT] + sot[t] + f * 4 + b; dlx.ins(u, t + n * m); Rep(i, 0, P.size()) dlx.ins(u, P[i]); return 1; } map<int, int> ans; void PTM() //Pretreatment { ans[3] = 8; ans[4] = 1472; ans[5] = 4040; ans[6] = 9356; } void PPT() //Pre-Pretreatment { Rep(i, 1, 31) if (i * i <= 60) { n = i; m = 60 / n; dlx.ini(MAXT + n * m); dlx.ms = n * m; Rep(pos, 0, n * m) Rep(t, 0, MAXT) Rep(i, 0, otm[t]) { if (t == 7 && i % 4 > 1) continue; //Because block 7 is centrosymmetry CAI(pos / m, pos % m, t, i / 4, i % 4); } dlx.edf(0); printf("%4d = %d\n", i, dlx.res); } } int main() { //PPT(); PTM(); while (~scanf("%d%d", &n, &m)) { //Initialize //Solve printf("%d\n", ans[min(n, m)] / 4); } return 0; }
hdu 2518 Dominoes
最新推荐文章于 2017-11-16 22:26:09 发布