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);
    }
}

 

posted @ 2017-01-19 15:18  AwD!  阅读(539)  评论(1编辑  收藏  举报