bzoj 2283: [Sdoi2011]火星移民
六边形插头dp题……
考虑将这张图推正,就像这样:
灵魂画师&
然后就可以编号了,这样就可以和矩形内一样跑插头dp了
转移一共有16种……防AK好好题
10.5k代码
啦啦啦~
#pragma GCC optimize (2) #include <bits/stdc++.h> #define N 14 #define MOD 1000000007 using namespace std; int n; int P[N][N * 2]; struct ct { int a[N]; ct() { for (int i = 0; i < N; ++ i) a[i] = 0; } }; inline int operator <(ct x, ct y) { for (int i = 0; i <= n * 2; ++ i) if (x.a[i] != y.a[i]) return x.a[i] < y.a[i]; return 0; } inline void maintain(ct &x) { int s[N]; int tot = 6; for (int i = 0; i < N; ++ i) s[i] = 0; for (int i = 0; i <= n * 2; ++ i) if (x.a[i] > 6 && !s[x.a[i]]) s[x.a[i]] = ++ tot; for (int i = 0; i <= n * 2; ++ i) if (x.a[i] > 6) x.a[i] = s[x.a[i]]; } struct p2 { int fr, sc; }; inline p2 mix(p2 x, p2 y) { if (x.fr < y.fr) return x; else if (x.fr > y.fr) return y; else return (p2){x.fr, (x.sc + y.sc) >= MOD? (x.sc + y.sc) - MOD: (x.sc + y.sc)}; } map <ct, p2> F[2]; ct fin; int tmp, vis[4]; void print(ct x) { for (int i = 0; i <= 2 * n; ++ i) printf("%d ", x.a[i]); puts(""); } int main() { while (scanf("%d", &n) == 1) { for (int i = 1; i <= n * 2; ++ i) for (int j = 1; j <= n * 4; ++ j) P[i][j] = 4; for (int i = 1; i <= n; ++ i) for (int j = n * 2 - i * 2 + 2; j <= n * 4; ++ j) scanf("%d", &P[i][j]); for (int i = n + 1; i <= n * 2; ++ i) for (int j = 1; j <= n * 6 - i * 2 + 1; ++ j) scanf("%d", &P[i][j]); for (int i = 0; i < 4; ++ i) vis[i] = 0; for (int i = 1; i <= n * 2; ++ i) for (int j = 1; j <= n * 4; ++ j) if (P[i][j] <= 3 && P[i][j]) { if (!vis[P[i][j]]) vis[P[i][j]] = 1, P[i][j] = P[i][j] * 2 - 1; else P[i][j] = P[i][j] * 2; } else if (P[i][j]) P[i][j] = 7; /* for (int i = 1; i <= n * 2; ++ i) { for (int j = 1; j <= n * 4; ++ j) printf("%d ", P[i][j]); puts(""); }*/ tmp = 0; F[0].clear(); F[1].clear(); F[0][fin] = (p2){0, 1}; for (int i = 1; i <= n * 2; ++ i) { for (int j = 1; j <= n * 2; ++ j) { tmp ^= 1; F[tmp].clear(); ct pf, nf; p2 ps, ns; for (map <ct, p2> :: iterator it = F[!tmp].begin(); it != F[!tmp].end(); ++ it) { pf = it -> first; ps = it -> second; // printf("%d %d %d : ", i, j * 2 - 1, ps.fr); print(pf); if (!P[i][j * 2 - 1]) { if (((bool)(pf.a[j - 1]) && (bool)(pf.a[j]))) { if (pf.a[j - 1] <= 6 && pf.a[j] <= 6) { if ((pf.a[j - 1] + 1) / 2 == (pf.a[j] + 1) / 2) { nf = pf; ns = ps; ns.fr ++; nf.a[j - 1] = nf.a[j] = 0; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else if (pf.a[j - 1] != pf.a[j]) { nf = pf; ns = ps; ns.fr ++; int mn = min(pf.a[j - 1], pf.a[j]), mx = max(pf.a[j - 1], pf.a[j]); for (int k = 0; k <= n * 2; ++ k) if (pf.a[k] == mx) nf.a[k] = mn; nf.a[j - 1] = nf.a[j] = 0; maintain(nf); if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else if ((bool)(pf.a[j - 1]) ^ (bool)(pf.a[j])) { nf = pf; ns = ps; ns.fr ++; nf.a[j - 1] = 0; nf.a[j] = pf.a[j - 1] + pf.a[j]; maintain(nf); if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } else { nf = pf; ns = ps; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else if (P[i][j * 2 - 1] == 7) { if (!(bool)(pf.a[j - 1]) && !(bool)(pf.a[j])) { nf = pf; ns = ps; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else { if ((bool)(pf.a[j - 1]) ^ (bool)(pf.a[j])) { if (pf.a[j - 1] + pf.a[j] <= 6) { if ((pf.a[j - 1] + pf.a[j] + 1) / 2 == (P[i][j * 2 - 1] + 1) / 2) { nf = pf; ns = ps; ns.fr ++; nf.a[j - 1] = nf.a[j] = 0; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else { nf = pf; ns = ps; ns.fr ++; int mx = max(pf.a[j - 1], pf.a[j]); for (int k = 0; k <= n * 2; ++ k) if (pf.a[k] == mx) nf.a[k] = P[i][j * 2 - 1]; nf.a[j - 1] = nf.a[j] = 0; maintain(nf); if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else if (!(bool)(pf.a[j - 1]) && !(bool)(pf.a[j])) { nf = pf; ns = ps; ns.fr ++; nf.a[j] = P[i][j * 2 - 1]; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } } tmp ^= 1; F[tmp].clear(); for (map <ct, p2> :: iterator it = F[!tmp].begin(); it != F[!tmp].end(); ++ it) { pf = it -> first; ps = it -> second; // printf("%d %d %d : ", i, j * 2, ps.fr); print(pf); if (!P[i][j * 2]) { if (pf.a[j]) { { nf = pf; ns = ps; ns.fr ++; nf.a[j - 1] = pf.a[j]; nf.a[j] = 0; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } { nf = pf; ns = ps; ns.fr ++; nf.a[j - 1] = 0; nf.a[j] = pf.a[j]; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else { { nf = pf; ns = ps; ns.fr ++; nf.a[j - 1] = nf.a[j] = N - 1; maintain(nf); if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } { nf = pf; ns = ps; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } } else if (P[i][j * 2] == 7) { if (!pf.a[j]) { nf = pf; ns = ps; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else { if (pf.a[j]) { if (pf.a[j] <= 6) { if ((pf.a[j] + 1) / 2 == (P[i][j * 2] + 1) / 2) { nf = pf; ns = ps; ns.fr ++; nf.a[j - 1] = nf.a[j] = 0; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else { nf = pf; ns = ps; ns.fr ++; for (int k = 0; k <= n * 2; ++ k) if (pf.a[k] == pf.a[j]) nf.a[k] = P[i][j * 2]; nf.a[j] = 0; maintain(nf); if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } else { { nf = pf; ns = ps; ns.fr ++; nf.a[j - 1] = P[i][j * 2]; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } { nf = pf; ns = ps; ns.fr ++; nf.a[j] = P[i][j * 2]; if (!F[tmp].count(nf)) F[tmp][nf] = ns; else F[tmp][nf] = mix(F[tmp][nf], ns); } } } } } tmp ^= 1; F[tmp].clear(); for (map <ct, p2> :: iterator it = F[!tmp].begin(); it != F[!tmp].end(); ++ it) { ct pf = it -> first, nf; p2 ps = it -> second; if (!pf.a[n * 2]) { for (int j = 1; j <= n * 2; ++ j) nf.a[j] = pf.a[j - 1]; F[tmp][nf] = ps; } } } p2 ans; if (F[tmp].count(fin)) ans = F[tmp][fin], ans.fr -= 3; else ans = (p2){-1, -1}; printf("%d %d\n", ans.fr, ans.sc); } }