zoukankan      html  css  js  c++  java
  • HDU 1693 Eat the Trees

    HDU_1639

        这个题目可以用插头dp的思想去做,由于允许多条回路,那么就只需要用0、1记录每个位置是否有插头,然后逐渐生成合法的状态并记录方案种数。

        更多和插头dp相关的题目可以参考胡浩的博客:http://www.notonlysuccess.com/index.php/plug-dp-complete/

    #include<stdio.h>
    #include<string.h>
    #define HASH 10007
    #define STATE 1000010
    #define MAXD 15
    int N, M, code[MAXD], maze[MAXD][MAXD];
    struct Hashmap
    {
        int head[HASH], next[STATE], state[STATE], size;
        long long f[STATE];
        void init()
        {
            memset(head, -1, sizeof(head));
            size = 0;
        }
        void push(int st, long long ans)
        {
            int i, h = st % HASH;
            for(i = head[h]; i != -1; i = next[i])
                if(st == state[i])
                {
                    f[i] += ans;
                    return ;
                }
            f[size] = ans, state[size] = st;
            next[size] = head[h];
            head[h] = size ++;
        }
    }hm[2];
    void decode(int *code, int m, int st)
    {
        int i;
        for(i = m; i >= 0; i --)
        {
            code[i] = st & 1;
            st >>= 1;
        }
    }
    int encode(int *code, int m)
    {
        int i, st = 0;
        for(i = 0; i <= m; i ++)
        {
            st <<= 1;
            st |= code[i];
        }
        return st;
    }
    void init()
    {
        int i, j, k;
        scanf("%d%d", &N, &M);
        memset(maze, 0, sizeof(maze));
        for(i = 1; i <= N; i ++)
            for(j = 1; j <= M; j ++)
                scanf("%d", &maze[i][j]);
    }
    void shift(int *code, int m)
    {
        int i;
        for(i = m; i > 0; i --)
            code[i] = code[i - 1];
        code[0] = 0;
    }
    void dpblank(int i, int j, int cur)
    {
        int k, left, up;
        for(k = 0; k < hm[cur].size; k ++)
        {
            decode(code, M, hm[cur].state[k]);
            left = code[j - 1], up = code[j];
            if(left && up)
            {
                code[j - 1] = code[j] = 0;
                if(j == M)
                    shift(code, M);
                hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
            }
            else if(left || up)
            {
                if(maze[i][j + 1])
                {
                    code[j - 1] = 0, code[j] = 1;
                    hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
                }
                if(maze[i + 1][j])
                {
                    code[j - 1] = 1, code[j] = 0;
                    if(j == M)
                        shift(code, M);
                    hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
                }
            }
            else
            {
                if(maze[i][j + 1] && maze[i + 1][j])
                {
                    code[j - 1] = code[j] = 1;
                    hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
                }
            }
        }
    }
    void dpblock(int i, int j, int cur)
    {
        int k;
        for(k = 0; k < hm[cur].size; k ++)
        {
            decode(code, M, hm[cur].state[k]);
            code[j - 1] = code[j] = 0;
            if(j == M)
                shift(code, M);
            hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
        }
    }
    void solve()
    {
        int i, j, cur = 0;
        long long ans = 0;
        hm[cur].init();
        hm[cur].push(0, 1);
        for(i = 1; i <= N; i ++)
            for(j = 1; j <= M; j ++)
            {
                hm[cur ^ 1].init();
                if(maze[i][j])
                    dpblank(i, j, cur);
                else
                    dpblock(i, j, cur);
                cur ^= 1;
            }
        for(i = 0; i < hm[cur].size; i ++)
            ans += hm[cur].f[i];
        printf("There are %I64d ways to eat the trees.\n", ans);
    }
    int main()
    {
        int t, tt;
        scanf("%d", &t);
        for(tt = 0; tt < t; tt ++)
        {
            init();
            printf("Case %d: ", tt + 1);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    CF 526F Max Mex(倍增求LCA+线段树路径合并)
    CoderForces Round526 (A~E)题解
    牛客OI周赛4-提高组 A K小生成树(kmst)
    Codeforces 1072 C
    Codeforces 1053 C
    牛客国庆集训派对Day3 B Tree
    牛客国庆集训派对Day3 I Metropolis
    牛客国庆集训派对Day3 A Knight
    牛客国庆集训派对Day3 G Stones
    Codeforces 1053 B
  • 原文地址:https://www.cnblogs.com/staginner/p/2456206.html
Copyright © 2011-2022 走看看